hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
author ysr
Sun, 16 Mar 2008 21:57:25 -0700
changeset 341 6578aad59716
parent 182 eae79d9b9d46
child 360 21d113ecbf6a
permissions -rw-r--r--
6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction Summary: The option CMSInitiatingPermOccupancyFraction now controls perm triggering threshold. Even though the actual value of the threshold has not yet been changed, so there is no change in policy, we now have the infrastructure in place for dynamically deciding when to collect the perm gen, an issue that will be addressed in the near future. Reviewed-by: jmasa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
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/_concurrentMarkSweepGeneration.cpp.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
// statics
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
bool          CMSCollector::_full_gc_requested          = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
// In support of CMS/VM thread synchronization
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
// We split use of the CGC_lock into 2 "levels".
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
// The low-level locking is of the usual CGC_lock monitor. We introduce
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
// a higher level "token" (hereafter "CMS token") built on top of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
// low level monitor (hereafter "CGC lock").
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
// The token-passing protocol gives priority to the VM thread. The
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
// CMS-lock doesn't provide any fairness guarantees, but clients
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
// should ensure that it is only held for very short, bounded
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
// durations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
// When either of the CMS thread or the VM thread is involved in
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
// collection operations during which it does not want the other
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
// thread to interfere, it obtains the CMS token.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
// If either thread tries to get the token while the other has
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
// it, that thread waits. However, if the VM thread and CMS thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
// both want the token, then the VM thread gets priority while the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
// CMS thread waits. This ensures, for instance, that the "concurrent"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
// phases of the CMS thread's work do not block out the VM thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
// for long periods of time as the CMS thread continues to hog
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
// the token. (See bug 4616232).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
// The baton-passing functions are, however, controlled by the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
// flags _foregroundGCShouldWait and _foregroundGCIsActive,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
// and here the low-level CMS lock, not the high level token,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
// ensures mutual exclusion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
// Two important conditions that we have to satisfy:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
// 1. if a thread does a low-level wait on the CMS lock, then it
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
//    relinquishes the CMS token if it were holding that token
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
//    when it acquired the low-level CMS lock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
// 2. any low-level notifications on the low-level lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
//    should only be sent when a thread has relinquished the token.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
// In the absence of either property, we'd have potential deadlock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
// We protect each of the CMS (concurrent and sequential) phases
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
// with the CMS _token_, not the CMS _lock_.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
// The only code protected by CMS lock is the token acquisition code
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
// itself, see ConcurrentMarkSweepThread::[de]synchronize(), and the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
// baton-passing code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
// Unfortunately, i couldn't come up with a good abstraction to factor and
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
// hide the naked CGC_lock manipulation in the baton-passing code
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
// further below. That's something we should try to do. Also, the proof
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
// of correctness of this 2-level locking scheme is far from obvious,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
// and potentially quite slippery. We have an uneasy supsicion, for instance,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
// that there may be a theoretical possibility of delay/starvation in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
// low-level lock/wait/notify scheme used for the baton-passing because of
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
// potential intereference with the priority scheme embodied in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
// CMS-token-passing protocol. See related comments at a CGC_lock->wait()
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
// invocation further below and marked with "XXX 20011219YSR".
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
// Indeed, as we note elsewhere, this may become yet more slippery
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
// in the presence of multiple CMS and/or multiple VM threads. XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
class CMSTokenSync: public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  bool _is_cms_thread;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
  CMSTokenSync(bool is_cms_thread):
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
    _is_cms_thread(is_cms_thread) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
    assert(is_cms_thread == Thread::current()->is_ConcurrentGC_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
           "Incorrect argument to constructor");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
    ConcurrentMarkSweepThread::synchronize(_is_cms_thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  ~CMSTokenSync() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
    assert(_is_cms_thread ?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
             ConcurrentMarkSweepThread::cms_thread_has_cms_token() :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
             ConcurrentMarkSweepThread::vm_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
          "Incorrect state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
    ConcurrentMarkSweepThread::desynchronize(_is_cms_thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
// Convenience class that does a CMSTokenSync, and then acquires
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
// upto three locks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
class CMSTokenSyncWithLocks: public CMSTokenSync {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
  // Note: locks are acquired in textual declaration order
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  // and released in the opposite order
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  MutexLockerEx _locker1, _locker2, _locker3;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
  CMSTokenSyncWithLocks(bool is_cms_thread, Mutex* mutex1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
                        Mutex* mutex2 = NULL, Mutex* mutex3 = NULL):
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
    CMSTokenSync(is_cms_thread),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
    _locker1(mutex1, Mutex::_no_safepoint_check_flag),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
    _locker2(mutex2, Mutex::_no_safepoint_check_flag),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
    _locker3(mutex3, Mutex::_no_safepoint_check_flag)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
  { }
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
// Wrapper class to temporarily disable icms during a foreground cms collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
class ICMSDisabler: public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
  // The ctor disables icms and wakes up the thread so it notices the change;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
  // the dtor re-enables icms.  Note that the CMSCollector methods will check
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
  // CMSIncrementalMode.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
  ICMSDisabler()  { CMSCollector::disable_icms(); CMSCollector::start_icms(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
  ~ICMSDisabler() { CMSCollector::enable_icms(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
//  Concurrent Mark-Sweep Generation /////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
NOT_PRODUCT(CompactibleFreeListSpace* debug_cms_space;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
// This struct contains per-thread things necessary to support parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
// young-gen collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
class CMSParGCThreadState: public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  CFLS_LAB lab;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  PromotionInfo promo;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
  // Constructor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  CMSParGCThreadState(CompactibleFreeListSpace* cfls) : lab(cfls) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
    promo.setSpace(cfls);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
     ReservedSpace rs, size_t initial_byte_size, int level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
     CardTableRS* ct, bool use_adaptive_freelists,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
     FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
  CardGeneration(rs, initial_byte_size, level, ct),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  _dilatation_factor(((double)MinChunkSize)/((double)(oopDesc::header_size()))),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  _debug_collection_type(Concurrent_collection_type)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  HeapWord* bottom = (HeapWord*) _virtual_space.low();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
  HeapWord* end    = (HeapWord*) _virtual_space.high();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
  _direct_allocated_words = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
    _numObjectsPromoted = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
    _numWordsPromoted = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
    _numObjectsAllocated = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
    _numWordsAllocated = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
  _cmsSpace = new CompactibleFreeListSpace(_bts, MemRegion(bottom, end),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
                                           use_adaptive_freelists,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
                                           dictionaryChoice);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
  NOT_PRODUCT(debug_cms_space = _cmsSpace;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
  if (_cmsSpace == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
    vm_exit_during_initialization(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
      "CompactibleFreeListSpace allocation failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
  _cmsSpace->_gen = this;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  _gc_stats = new CMSGCStats();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
  // Verify the assumption that FreeChunk::_prev and OopDesc::_klass
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  // offsets match. The ability to tell free chunks from objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
  // depends on this property.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  debug_only(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
    FreeChunk* junk = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
    assert(junk->prev_addr() == (void*)(oop(junk)->klass_addr()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
           "Offset of FreeChunk::_prev within FreeChunk must match"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
           "  that of OopDesc::_klass within OopDesc");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
  if (ParallelGCThreads > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
    typedef CMSParGCThreadState* CMSParGCThreadStatePtr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
    _par_gc_thread_states =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
      NEW_C_HEAP_ARRAY(CMSParGCThreadStatePtr, ParallelGCThreads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
    if (_par_gc_thread_states == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
      vm_exit_during_initialization("Could not allocate par gc structs");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
    for (uint i = 0; i < ParallelGCThreads; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
      _par_gc_thread_states[i] = new CMSParGCThreadState(cmsSpace());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
      if (_par_gc_thread_states[i] == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
        vm_exit_during_initialization("Could not allocate par gc structs");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
    _par_gc_thread_states = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
  _incremental_collection_failed = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
  // The "dilatation_factor" is the expansion that can occur on
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
  // account of the fact that the minimum object size in the CMS
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
  // generation may be larger than that in, say, a contiguous young
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
  //  generation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
  // Ideally, in the calculation below, we'd compute the dilatation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
  // factor as: MinChunkSize/(promoting_gen's min object size)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
  // Since we do not have such a general query interface for the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
  // promoting generation, we'll instead just use the mimimum
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
  // object size (which today is a header's worth of space);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
  // note that all arithmetic is in units of HeapWords.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
  assert(MinChunkSize >= oopDesc::header_size(), "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  assert(_dilatation_factor >= 1.0, "from previous assert");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   228
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   229
// The field "_initiating_occupancy" represents the occupancy percentage
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   230
// at which we trigger a new collection cycle.  Unless explicitly specified
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   231
// via CMSInitiating[Perm]OccupancyFraction (argument "io" below), it
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   232
// is calculated by:
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   233
//
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   234
//   Let "f" be MinHeapFreeRatio in
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   235
//
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   236
//    _intiating_occupancy = 100-f +
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   237
//                           f * (CMSTrigger[Perm]Ratio/100)
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   238
//   where CMSTrigger[Perm]Ratio is the argument "tr" below.
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   239
//
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   240
// That is, if we assume the heap is at its desired maximum occupancy at the
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   241
// end of a collection, we let CMSTrigger[Perm]Ratio of the (purported) free
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   242
// space be allocated before initiating a new collection cycle.
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   243
//
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   244
void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   245
  assert(io <= 100 && tr >= 0 && tr <= 100, "Check the arguments");
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   246
  if (io >= 0) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   247
    _initiating_occupancy = (double)io / 100.0;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   248
  } else {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   249
    _initiating_occupancy = ((100 - MinHeapFreeRatio) +
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   250
                             (double)(tr * MinHeapFreeRatio) / 100.0)
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   251
                            / 100.0;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   252
  }
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   253
}
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   254
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   255
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
void ConcurrentMarkSweepGeneration::ref_processor_init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
  assert(collector() != NULL, "no collector");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
  collector()->ref_processor_init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
void CMSCollector::ref_processor_init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
  if (_ref_processor == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
    // Allocate and initialize a reference processor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
    _ref_processor = ReferenceProcessor::create_ref_processor(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
        _span,                               // span
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
        _cmsGen->refs_discovery_is_atomic(), // atomic_discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
        _cmsGen->refs_discovery_is_mt(),     // mt_discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
        &_is_alive_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
        ParallelGCThreads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
        ParallelRefProcEnabled);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
    // Initialize the _ref_processor field of CMSGen
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
    _cmsGen->set_ref_processor(_ref_processor);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
    // Allocate a dummy ref processor for perm gen.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
    ReferenceProcessor* rp2 = new ReferenceProcessor();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
    if (rp2 == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
      vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
    _permGen->set_ref_processor(rp2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
CMSAdaptiveSizePolicy* CMSCollector::size_policy() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
    "Wrong type of heap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
  CMSAdaptiveSizePolicy* sp = (CMSAdaptiveSizePolicy*)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
    gch->gen_policy()->size_policy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
  assert(sp->is_gc_cms_adaptive_size_policy(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
    "Wrong type of size policy");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  return sp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
CMSGCAdaptivePolicyCounters* CMSCollector::gc_adaptive_policy_counters() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
  CMSGCAdaptivePolicyCounters* results =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
    (CMSGCAdaptivePolicyCounters*) collector_policy()->counters();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
  assert(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
    results->kind() == GCPolicyCounters::CMSGCAdaptivePolicyCountersKind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
    "Wrong gc policy counter kind");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
  return results;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
void ConcurrentMarkSweepGeneration::initialize_performance_counters() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  const char* gen_name = "old";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
  // Generation Counters - generation 1, 1 subspace
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
  _gen_counters = new GenerationCounters(gen_name, 1, 1, &_virtual_space);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
  _space_counters = new GSpaceCounters(gen_name, 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
                                       _virtual_space.reserved_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
                                       this, _gen_counters);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
CMSStats::CMSStats(ConcurrentMarkSweepGeneration* cms_gen, unsigned int alpha):
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
  _cms_gen(cms_gen)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
  assert(alpha <= 100, "bad value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
  _saved_alpha = alpha;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
  // Initialize the alphas to the bootstrap value of 100.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
  _gc0_alpha = _cms_alpha = 100;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
  _cms_begin_time.update();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
  _cms_end_time.update();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
  _gc0_duration = 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
  _gc0_period = 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
  _gc0_promoted = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
  _cms_duration = 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
  _cms_period = 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
  _cms_allocated = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  _cms_used_at_gc0_begin = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
  _cms_used_at_gc0_end = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
  _allow_duty_cycle_reduction = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
  _valid_bits = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
  _icms_duty_cycle = CMSIncrementalDutyCycle;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
// If promotion failure handling is on use
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
// the padded average size of the promotion for each
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
// young generation collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
double CMSStats::time_until_cms_gen_full() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
  size_t cms_free = _cms_gen->cmsSpace()->free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
  size_t expected_promotion = gch->get_gen(0)->capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  if (HandlePromotionFailure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
    expected_promotion = MIN2(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
        (size_t) _cms_gen->gc_stats()->avg_promoted()->padded_average(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
        expected_promotion);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
  if (cms_free > expected_promotion) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
    // Start a cms collection if there isn't enough space to promote
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
    // for the next minor collection.  Use the padded average as
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
    // a safety factor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
    cms_free -= expected_promotion;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
    // Adjust by the safety factor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
    double cms_free_dbl = (double)cms_free;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
    cms_free_dbl = cms_free_dbl * (100.0 - CMSIncrementalSafetyFactor) / 100.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
      gclog_or_tty->print_cr("CMSStats::time_until_cms_gen_full: cms_free "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
        SIZE_FORMAT " expected_promotion " SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
        cms_free, expected_promotion);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
      gclog_or_tty->print_cr("  cms_free_dbl %f cms_consumption_rate %f",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
        cms_free_dbl, cms_consumption_rate() + 1.0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
    // Add 1 in case the consumption rate goes to zero.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
    return cms_free_dbl / (cms_consumption_rate() + 1.0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
  return 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
// Compare the duration of the cms collection to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
// time remaining before the cms generation is empty.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
// Note that the time from the start of the cms collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
// to the start of the cms sweep (less than the total
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
// duration of the cms collection) can be used.  This
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
// has been tried and some applications experienced
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
// promotion failures early in execution.  This was
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
// possibly because the averages were not accurate
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
// enough at the beginning.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
double CMSStats::time_until_cms_start() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
  // We add "gc0_period" to the "work" calculation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
  // below because this query is done (mostly) at the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
  // end of a scavenge, so we need to conservatively
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
  // account for that much possible delay
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
  // in the query so as to avoid concurrent mode failures
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
  // due to starting the collection just a wee bit too
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
  // late.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  double work = cms_duration() + gc0_period();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
  double deadline = time_until_cms_gen_full();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  if (work > deadline) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
    if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
      gclog_or_tty->print(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
        " CMSCollector: collect because of anticipated promotion "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
        "before full %3.7f + %3.7f > %3.7f ", cms_duration(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
        gc0_period(), time_until_cms_gen_full());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
    return 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
  return work - deadline;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
// Return a duty cycle based on old_duty_cycle and new_duty_cycle, limiting the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
// amount of change to prevent wild oscillation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
unsigned int CMSStats::icms_damped_duty_cycle(unsigned int old_duty_cycle,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
                                              unsigned int new_duty_cycle) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
  assert(old_duty_cycle <= 100, "bad input value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
  assert(new_duty_cycle <= 100, "bad input value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
  // Note:  use subtraction with caution since it may underflow (values are
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
  // unsigned).  Addition is safe since we're in the range 0-100.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
  unsigned int damped_duty_cycle = new_duty_cycle;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
  if (new_duty_cycle < old_duty_cycle) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
    const unsigned int largest_delta = MAX2(old_duty_cycle / 4, 5U);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
    if (new_duty_cycle + largest_delta < old_duty_cycle) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
      damped_duty_cycle = old_duty_cycle - largest_delta;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
  } else if (new_duty_cycle > old_duty_cycle) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
    const unsigned int largest_delta = MAX2(old_duty_cycle / 4, 15U);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
    if (new_duty_cycle > old_duty_cycle + largest_delta) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
      damped_duty_cycle = MIN2(old_duty_cycle + largest_delta, 100U);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
  assert(damped_duty_cycle <= 100, "invalid duty cycle computed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
  if (CMSTraceIncrementalPacing) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
    gclog_or_tty->print(" [icms_damped_duty_cycle(%d,%d) = %d] ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
                           old_duty_cycle, new_duty_cycle, damped_duty_cycle);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
  return damped_duty_cycle;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
unsigned int CMSStats::icms_update_duty_cycle_impl() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
  assert(CMSIncrementalPacing && valid(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
         "should be handled in icms_update_duty_cycle()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
  double cms_time_so_far = cms_timer().seconds();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
  double scaled_duration = cms_duration_per_mb() * _cms_used_at_gc0_end / M;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
  double scaled_duration_remaining = fabsd(scaled_duration - cms_time_so_far);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
  // Avoid division by 0.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  double time_until_full = MAX2(time_until_cms_gen_full(), 0.01);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
  double duty_cycle_dbl = 100.0 * scaled_duration_remaining / time_until_full;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
  unsigned int new_duty_cycle = MIN2((unsigned int)duty_cycle_dbl, 100U);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
  if (new_duty_cycle > _icms_duty_cycle) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
    // Avoid very small duty cycles (1 or 2); 0 is allowed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
    if (new_duty_cycle > 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
      _icms_duty_cycle = icms_damped_duty_cycle(_icms_duty_cycle,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
                                                new_duty_cycle);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
  } else if (_allow_duty_cycle_reduction) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
    // The duty cycle is reduced only once per cms cycle (see record_cms_end()).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
    new_duty_cycle = icms_damped_duty_cycle(_icms_duty_cycle, new_duty_cycle);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
    // Respect the minimum duty cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
    unsigned int min_duty_cycle = (unsigned int)CMSIncrementalDutyCycleMin;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
    _icms_duty_cycle = MAX2(new_duty_cycle, min_duty_cycle);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
  if (PrintGCDetails || CMSTraceIncrementalPacing) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
    gclog_or_tty->print(" icms_dc=%d ", _icms_duty_cycle);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
  _allow_duty_cycle_reduction = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
  return _icms_duty_cycle;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
void CMSStats::print_on(outputStream *st) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
  st->print(" gc0_alpha=%d,cms_alpha=%d", _gc0_alpha, _cms_alpha);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
  st->print(",gc0_dur=%g,gc0_per=%g,gc0_promo=" SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
               gc0_duration(), gc0_period(), gc0_promoted());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
  st->print(",cms_dur=%g,cms_dur_per_mb=%g,cms_per=%g,cms_alloc=" SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
            cms_duration(), cms_duration_per_mb(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
            cms_period(), cms_allocated());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
  st->print(",cms_since_beg=%g,cms_since_end=%g",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
            cms_time_since_begin(), cms_time_since_end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
  st->print(",cms_used_beg=" SIZE_FORMAT ",cms_used_end=" SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
            _cms_used_at_gc0_begin, _cms_used_at_gc0_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
  if (CMSIncrementalMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
    st->print(",dc=%d", icms_duty_cycle());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
  if (valid()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
    st->print(",promo_rate=%g,cms_alloc_rate=%g",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
              promotion_rate(), cms_allocation_rate());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
    st->print(",cms_consumption_rate=%g,time_until_full=%g",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
              cms_consumption_rate(), time_until_cms_gen_full());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
  st->print(" ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
#endif // #ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
CMSCollector::CollectorState CMSCollector::_collectorState =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
                             CMSCollector::Idling;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
bool CMSCollector::_foregroundGCIsActive = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
bool CMSCollector::_foregroundGCShouldWait = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
                           ConcurrentMarkSweepGeneration* permGen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
                           CardTableRS*                   ct,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
                           ConcurrentMarkSweepPolicy*     cp):
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
  _cmsGen(cmsGen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
  _permGen(permGen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
  _ct(ct),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
  _ref_processor(NULL),    // will be set later
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
  _conc_workers(NULL),     // may be set later
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
  _abort_preclean(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
  _start_sampling(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
  _between_prologue_and_epilogue(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
  _markBitMap(0, Mutex::leaf + 1, "CMS_markBitMap_lock"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
  _perm_gen_verify_bit_map(0, -1 /* no mutex */, "No_lock"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
  _modUnionTable((CardTableModRefBS::card_shift - LogHeapWordSize),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
                 -1 /* lock-free */, "No_lock" /* dummy */),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
  _modUnionClosure(&_modUnionTable),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
  _modUnionClosurePar(&_modUnionTable),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
  _is_alive_closure(&_markBitMap),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
  _restart_addr(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
  _overflow_list(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
  _preserved_oop_stack(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
  _preserved_mark_stack(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
  _stats(cmsGen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
  _eden_chunk_array(NULL),     // may be set in ctor body
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
  _eden_chunk_capacity(0),     // -- ditto --
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  _eden_chunk_index(0),        // -- ditto --
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  _survivor_plab_array(NULL),  // -- ditto --
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
  _survivor_chunk_array(NULL), // -- ditto --
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
  _survivor_chunk_capacity(0), // -- ditto --
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
  _survivor_chunk_index(0),    // -- ditto --
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
  _ser_pmc_preclean_ovflw(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
  _ser_pmc_remark_ovflw(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
  _par_pmc_remark_ovflw(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
  _ser_kac_ovflw(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
  _par_kac_ovflw(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
  _num_par_pushes(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
  _collection_count_start(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
  _verifying(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
  _icms_start_limit(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
  _icms_stop_limit(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
  _verification_mark_bm(0, Mutex::leaf + 1, "CMS_verification_mark_bm_lock"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
  _completed_initialization(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
  _collector_policy(cp),
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   551
  _should_unload_classes(false),
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   552
  _concurrent_cycles_since_last_unload(0),
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
  _sweep_estimate(CMS_SweepWeight, CMS_SweepPadding)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
  if (ExplicitGCInvokesConcurrentAndUnloadsClasses) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
    ExplicitGCInvokesConcurrent = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
  // Now expand the span and allocate the collection support structures
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
  // (MUT, marking bit map etc.) to cover both generations subject to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
  // collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
  // First check that _permGen is adjacent to _cmsGen and above it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
  assert(   _cmsGen->reserved().word_size()  > 0
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
         && _permGen->reserved().word_size() > 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
         "generations should not be of zero size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
  assert(_cmsGen->reserved().intersection(_permGen->reserved()).is_empty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
         "_cmsGen and _permGen should not overlap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
  assert(_cmsGen->reserved().end() == _permGen->reserved().start(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
         "_cmsGen->end() different from _permGen->start()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
  // For use by dirty card to oop closures.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
  _cmsGen->cmsSpace()->set_collector(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
  _permGen->cmsSpace()->set_collector(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
  // Adjust my span to cover old (cms) gen and perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
  _span = _cmsGen->reserved()._union(_permGen->reserved());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
  // Initialize the span of is_alive_closure
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
  _is_alive_closure.set_span(_span);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
  // Allocate MUT and marking bit map
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
    MutexLockerEx x(_markBitMap.lock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
    if (!_markBitMap.allocate(_span)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
      warning("Failed to allocate CMS Bit Map");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
    assert(_markBitMap.covers(_span), "_markBitMap inconsistency?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
    _modUnionTable.allocate(_span);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
    assert(_modUnionTable.covers(_span), "_modUnionTable inconsistency?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
  if (!_markStack.allocate(CMSMarkStackSize)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
    warning("Failed to allocate CMS Marking Stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
  if (!_revisitStack.allocate(CMSRevisitStackSize)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
    warning("Failed to allocate CMS Revisit Stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
  // Support for multi-threaded concurrent phases
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
  if (ParallelGCThreads > 0 && CMSConcurrentMTEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
    if (FLAG_IS_DEFAULT(ParallelCMSThreads)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
      // just for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
      FLAG_SET_DEFAULT(ParallelCMSThreads, (ParallelGCThreads + 3)/4);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
    if (ParallelCMSThreads > 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
      _conc_workers = new YieldingFlexibleWorkGang("Parallel CMS Threads",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
                                 ParallelCMSThreads, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
      if (_conc_workers == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
        warning("GC/CMS: _conc_workers allocation failure: "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
              "forcing -CMSConcurrentMTEnabled");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
        CMSConcurrentMTEnabled = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
      CMSConcurrentMTEnabled = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
  if (!CMSConcurrentMTEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
    ParallelCMSThreads = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
    // Turn off CMSCleanOnEnter optimization temporarily for
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
    // the MT case where it's not fixed yet; see 6178663.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
    CMSCleanOnEnter = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
  assert((_conc_workers != NULL) == (ParallelCMSThreads > 1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
         "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
  // Parallel task queues; these are shared for the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
  // concurrent and stop-world phases of CMS, but
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
  // are not shared with parallel scavenge (ParNew).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
    uint i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
    uint num_queues = (uint) MAX2(ParallelGCThreads, ParallelCMSThreads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
    if ((CMSParallelRemarkEnabled || CMSConcurrentMTEnabled
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
         || ParallelRefProcEnabled)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
        && num_queues > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
      _task_queues = new OopTaskQueueSet(num_queues);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
      if (_task_queues == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
        warning("task_queues allocation failure.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
        return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
      _hash_seed = NEW_C_HEAP_ARRAY(int, num_queues);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
      if (_hash_seed == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
        warning("_hash_seed array allocation failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
        return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
      // XXX use a global constant instead of 64!
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
      typedef struct OopTaskQueuePadded {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
        OopTaskQueue work_queue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
        char pad[64 - sizeof(OopTaskQueue)];  // prevent false sharing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
      } OopTaskQueuePadded;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
      for (i = 0; i < num_queues; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
        OopTaskQueuePadded *q_padded = new OopTaskQueuePadded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
        if (q_padded == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
          warning("work_queue allocation failure.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
          return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
        _task_queues->register_queue(i, &q_padded->work_queue);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
      for (i = 0; i < num_queues; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
        _task_queues->queue(i)->initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
        _hash_seed[i] = 17;  // copied from ParNew
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   673
  _cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio);
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   674
  _permGen->init_initiating_occupancy(CMSInitiatingPermOccupancyFraction, CMSTriggerPermRatio);
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   675
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
  // Clip CMSBootstrapOccupancy between 0 and 100.
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
   677
  _bootstrap_occupancy = ((double)MIN2((uintx)100, MAX2((uintx)0, CMSBootstrapOccupancy)))
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
                         /(double)100;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
  _full_gcs_since_conc_gc = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
  // Now tell CMS generations the identity of their collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
  ConcurrentMarkSweepGeneration::set_collector(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
  // Create & start a CMS thread for this CMS collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
  _cmsThread = ConcurrentMarkSweepThread::start(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
  assert(cmsThread() != NULL, "CMS Thread should have been created");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
  assert(cmsThread()->collector() == this,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
         "CMS Thread should refer to this gen");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
  assert(CGC_lock != NULL, "Where's the CGC_lock?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
  // Support for parallelizing young gen rescan
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
  _young_gen = gch->prev_gen(_cmsGen);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
  if (gch->supports_inline_contig_alloc()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
    _top_addr = gch->top_addr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
    _end_addr = gch->end_addr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
    assert(_young_gen != NULL, "no _young_gen");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
    _eden_chunk_index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
    _eden_chunk_capacity = (_young_gen->max_capacity()+CMSSamplingGrain)/CMSSamplingGrain;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
    _eden_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, _eden_chunk_capacity);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
    if (_eden_chunk_array == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
      _eden_chunk_capacity = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
      warning("GC/CMS: _eden_chunk_array allocation failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
  assert(_eden_chunk_array != NULL || _eden_chunk_capacity == 0, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
  // Support for parallelizing survivor space rescan
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
  if (CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
    size_t max_plab_samples = MaxNewSize/((SurvivorRatio+2)*MinTLABSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
    _survivor_plab_array  = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
    _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
    _cursor               = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
    if (_survivor_plab_array == NULL || _survivor_chunk_array == NULL
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
        || _cursor == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
      warning("Failed to allocate survivor plab/chunk array");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
      if (_survivor_plab_array  != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
        FREE_C_HEAP_ARRAY(ChunkArray, _survivor_plab_array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
        _survivor_plab_array = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
      if (_survivor_chunk_array != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
        FREE_C_HEAP_ARRAY(HeapWord*, _survivor_chunk_array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
        _survivor_chunk_array = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
      if (_cursor != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
        FREE_C_HEAP_ARRAY(size_t, _cursor);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
        _cursor = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
      _survivor_chunk_capacity = 2*max_plab_samples;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
      for (uint i = 0; i < ParallelGCThreads; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
        HeapWord** vec = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
        if (vec == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
          warning("Failed to allocate survivor plab array");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
          for (int j = i; j > 0; j--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
            FREE_C_HEAP_ARRAY(HeapWord*, _survivor_plab_array[j-1].array());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
          FREE_C_HEAP_ARRAY(ChunkArray, _survivor_plab_array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
          FREE_C_HEAP_ARRAY(HeapWord*, _survivor_chunk_array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
          _survivor_plab_array = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
          _survivor_chunk_array = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
          _survivor_chunk_capacity = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
          break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
          ChunkArray* cur =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
            ::new (&_survivor_plab_array[i]) ChunkArray(vec,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
                                                        max_plab_samples);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
          assert(cur->end() == 0, "Should be 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
          assert(cur->array() == vec, "Should be vec");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
          assert(cur->capacity() == max_plab_samples, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
  assert(   (   _survivor_plab_array  != NULL
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
             && _survivor_chunk_array != NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
         || (   _survivor_chunk_capacity == 0
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
             && _survivor_chunk_index == 0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
         "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
  // Choose what strong roots should be scanned depending on verification options
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
  // and perm gen collection mode.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
  if (!CMSClassUnloadingEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
    // If class unloading is disabled we want to include all classes into the root set.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
    add_root_scanning_option(SharedHeap::SO_AllClasses);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
    add_root_scanning_option(SharedHeap::SO_SystemClasses);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
  NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
  _gc_counters = new CollectorCounters("CMS", 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
  _completed_initialization = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
  _sweep_timer.start();  // start of time
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
const char* ConcurrentMarkSweepGeneration::name() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
  return "concurrent mark-sweep generation";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
void ConcurrentMarkSweepGeneration::update_counters() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
    _space_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
    _gen_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
// this is an optimized version of update_counters(). it takes the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
// used value as a parameter rather than computing it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
void ConcurrentMarkSweepGeneration::update_counters(size_t used) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
    _space_counters->update_used(used);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
    _space_counters->update_capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
    _gen_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
void ConcurrentMarkSweepGeneration::print() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
  Generation::print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
  cmsSpace()->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
void ConcurrentMarkSweepGeneration::print_statistics() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
  cmsSpace()->printFLCensus(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
void ConcurrentMarkSweepGeneration::printOccupancy(const char *s) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
  if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
    if (Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
      gclog_or_tty->print(" [%d %s-%s: "SIZE_FORMAT"("SIZE_FORMAT")]",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
        level(), short_name(), s, used(), capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
      gclog_or_tty->print(" [%d %s-%s: "SIZE_FORMAT"K("SIZE_FORMAT"K)]",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
        level(), short_name(), s, used() / K, capacity() / K);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   820
  if (Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
    gclog_or_tty->print(" "SIZE_FORMAT"("SIZE_FORMAT")",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   822
              gch->used(), gch->capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   823
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   824
    gclog_or_tty->print(" "SIZE_FORMAT"K("SIZE_FORMAT"K)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
              gch->used() / K, gch->capacity() / K);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   827
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
size_t
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
ConcurrentMarkSweepGeneration::contiguous_available() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
  // dld proposes an improvement in precision here. If the committed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
  // part of the space ends in a free block we should add that to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
  // uncommitted size in the calculation below. Will make this
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
  // change later, staying with the approximation below for the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
  // time being. -- ysr.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
  return MAX2(_virtual_space.uncommitted_size(), unsafe_max_alloc_nogc());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
size_t
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
ConcurrentMarkSweepGeneration::unsafe_max_alloc_nogc() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
  return _cmsSpace->max_alloc_in_words() * HeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
size_t ConcurrentMarkSweepGeneration::max_available() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
  return free() + _virtual_space.uncommitted_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
    size_t max_promotion_in_bytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
    bool younger_handles_promotion_failure) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
  // This is the most conservative test.  Full promotion is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   853
  // guaranteed if this is used. The multiplicative factor is to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
  // account for the worst case "dilatation".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
  double adjusted_max_promo_bytes = _dilatation_factor * max_promotion_in_bytes;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
  if (adjusted_max_promo_bytes > (double)max_uintx) { // larger than size_t
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
    adjusted_max_promo_bytes = (double)max_uintx;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
  bool result = (max_contiguous_available() >= (size_t)adjusted_max_promo_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
  if (younger_handles_promotion_failure && !result) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
    // Full promotion is not guaranteed because fragmentation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
    // of the cms generation can prevent the full promotion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
    result = (max_available() >= (size_t)adjusted_max_promo_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
    if (!result) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
      // With promotion failure handling the test for the ability
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
      // to support the promotion does not have to be guaranteed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
      // Use an average of the amount promoted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
      result = max_available() >= (size_t)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
        gc_stats()->avg_promoted()->padded_average();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
      if (PrintGC && Verbose && result) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
        gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
          "\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
          " max_available: " SIZE_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
          " avg_promoted: " SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
          max_available(), (size_t)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
          gc_stats()->avg_promoted()->padded_average());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
      if (PrintGC && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
        gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
          "\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
          " max_available: " SIZE_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
          " adj_max_promo_bytes: " SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
          max_available(), (size_t)adjusted_max_promo_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
    if (PrintGC && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
      gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
        "\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
        " contiguous_available: " SIZE_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
        " adj_max_promo_bytes: " SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
        max_contiguous_available(), (size_t)adjusted_max_promo_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
CompactibleSpace*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
ConcurrentMarkSweepGeneration::first_compaction_space() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
  return _cmsSpace;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
void ConcurrentMarkSweepGeneration::reset_after_compaction() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
  // Clear the promotion information.  These pointers can be adjusted
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
  // along with all the other pointers into the heap but
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
  // compaction is expected to be a rare event with
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
  // a heap using cms so don't do it without seeing the need.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
  if (ParallelGCThreads > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
    for (uint i = 0; i < ParallelGCThreads; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   913
      _par_gc_thread_states[i]->promo.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
void ConcurrentMarkSweepGeneration::space_iterate(SpaceClosure* blk, bool usedOnly) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
  blk->do_space(_cmsSpace);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
void ConcurrentMarkSweepGeneration::compute_new_size() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   923
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   924
489c9b5090e2 Initial load
duke
parents:
diff changeset
   925
  // If incremental collection failed, we just want to expand
489c9b5090e2 Initial load
duke
parents:
diff changeset
   926
  // to the limit.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   927
  if (incremental_collection_failed()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   928
    clear_incremental_collection_failed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   929
    grow_to_reserved();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   930
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   931
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   932
489c9b5090e2 Initial load
duke
parents:
diff changeset
   933
  size_t expand_bytes = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   934
  double free_percentage = ((double) free()) / capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   935
  double desired_free_percentage = (double) MinHeapFreeRatio / 100;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   936
  double maximum_free_percentage = (double) MaxHeapFreeRatio / 100;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   937
489c9b5090e2 Initial load
duke
parents:
diff changeset
   938
  // compute expansion delta needed for reaching desired free percentage
489c9b5090e2 Initial load
duke
parents:
diff changeset
   939
  if (free_percentage < desired_free_percentage) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   940
    size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   941
    assert(desired_capacity >= capacity(), "invalid expansion size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   942
    expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   943
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   944
  if (expand_bytes > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   945
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   946
      size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   947
      gclog_or_tty->print_cr("\nFrom compute_new_size: ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   948
      gclog_or_tty->print_cr("  Free fraction %f", free_percentage);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   949
      gclog_or_tty->print_cr("  Desired free fraction %f",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   950
        desired_free_percentage);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   951
      gclog_or_tty->print_cr("  Maximum free fraction %f",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   952
        maximum_free_percentage);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   953
      gclog_or_tty->print_cr("  Capactiy "SIZE_FORMAT, capacity()/1000);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   954
      gclog_or_tty->print_cr("  Desired capacity "SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   955
        desired_capacity/1000);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   956
      int prev_level = level() - 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   957
      if (prev_level >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   958
        size_t prev_size = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   959
        GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   960
        Generation* prev_gen = gch->_gens[prev_level];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   961
        prev_size = prev_gen->capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   962
          gclog_or_tty->print_cr("  Younger gen size "SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   963
                                 prev_size/1000);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   964
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   965
      gclog_or_tty->print_cr("  unsafe_max_alloc_nogc "SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   966
        unsafe_max_alloc_nogc()/1000);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   967
      gclog_or_tty->print_cr("  contiguous available "SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   968
        contiguous_available()/1000);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   969
      gclog_or_tty->print_cr("  Expand by "SIZE_FORMAT" (bytes)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   970
        expand_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   971
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   972
    // safe if expansion fails
489c9b5090e2 Initial load
duke
parents:
diff changeset
   973
    expand(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   974
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   975
      gclog_or_tty->print_cr("  Expanded free fraction %f",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   976
        ((double) free()) / capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   977
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   978
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   979
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   980
489c9b5090e2 Initial load
duke
parents:
diff changeset
   981
Mutex* ConcurrentMarkSweepGeneration::freelistLock() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   982
  return cmsSpace()->freelistLock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   983
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   984
489c9b5090e2 Initial load
duke
parents:
diff changeset
   985
HeapWord* ConcurrentMarkSweepGeneration::allocate(size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   986
                                                  bool   tlab) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   987
  CMSSynchronousYieldRequest yr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   988
  MutexLockerEx x(freelistLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   989
                  Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   990
  return have_lock_and_allocate(size, tlab);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   991
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   992
489c9b5090e2 Initial load
duke
parents:
diff changeset
   993
HeapWord* ConcurrentMarkSweepGeneration::have_lock_and_allocate(size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   994
                                                  bool   tlab) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   995
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   996
  size_t adjustedSize = CompactibleFreeListSpace::adjustObjectSize(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   997
  HeapWord* res = cmsSpace()->allocate(adjustedSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   998
  // Allocate the object live (grey) if the background collector has
489c9b5090e2 Initial load
duke
parents:
diff changeset
   999
  // started marking. This is necessary because the marker may
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1000
  // have passed this address and consequently this object will
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1001
  // not otherwise be greyed and would be incorrectly swept up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1002
  // Note that if this object contains references, the writing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1003
  // of those references will dirty the card containing this object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1004
  // allowing the object to be blackened (and its references scanned)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1005
  // either during a preclean phase or at the final checkpoint.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1006
  if (res != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1007
    collector()->direct_allocated(res, adjustedSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1008
    _direct_allocated_words += adjustedSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1009
    // allocation counters
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1010
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1011
      _numObjectsAllocated++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1012
      _numWordsAllocated += (int)adjustedSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1013
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1014
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1015
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1016
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1017
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1018
// In the case of direct allocation by mutators in a generation that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1019
// is being concurrently collected, the object must be allocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1020
// live (grey) if the background collector has started marking.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1021
// This is necessary because the marker may
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1022
// have passed this address and consequently this object will
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1023
// not otherwise be greyed and would be incorrectly swept up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1024
// Note that if this object contains references, the writing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1025
// of those references will dirty the card containing this object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1026
// allowing the object to be blackened (and its references scanned)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1027
// either during a preclean phase or at the final checkpoint.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1028
void CMSCollector::direct_allocated(HeapWord* start, size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1029
  assert(_markBitMap.covers(start, size), "Out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1030
  if (_collectorState >= Marking) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1031
    MutexLockerEx y(_markBitMap.lock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1032
                    Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1033
    // [see comments preceding SweepClosure::do_blk() below for details]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1034
    // 1. need to mark the object as live so it isn't collected
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1035
    // 2. need to mark the 2nd bit to indicate the object may be uninitialized
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1036
    // 3. need to mark the end of the object so sweeper can skip over it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1037
    //    if it's uninitialized when the sweeper reaches it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1038
    _markBitMap.mark(start);          // object is live
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1039
    _markBitMap.mark(start + 1);      // object is potentially uninitialized?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1040
    _markBitMap.mark(start + size - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1041
                                      // mark end of object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1042
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1043
  // check that oop looks uninitialized
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1044
  assert(oop(start)->klass() == NULL, "_klass should be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1045
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1046
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1047
void CMSCollector::promoted(bool par, HeapWord* start,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1048
                            bool is_obj_array, size_t obj_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1049
  assert(_markBitMap.covers(start), "Out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1050
  // See comment in direct_allocated() about when objects should
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1051
  // be allocated live.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1052
  if (_collectorState >= Marking) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1053
    // we already hold the marking bit map lock, taken in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1054
    // the prologue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1055
    if (par) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1056
      _markBitMap.par_mark(start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1057
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1058
      _markBitMap.mark(start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1059
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1060
    // We don't need to mark the object as uninitialized (as
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1061
    // in direct_allocated above) because this is being done with the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1062
    // world stopped and the object will be initialized by the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1063
    // time the sweeper gets to look at it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1064
    assert(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1065
           "expect promotion only at safepoints");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1066
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1067
    if (_collectorState < Sweeping) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1068
      // Mark the appropriate cards in the modUnionTable, so that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1069
      // this object gets scanned before the sweep. If this is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1070
      // not done, CMS generation references in the object might
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1071
      // not get marked.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1072
      // For the case of arrays, which are otherwise precisely
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1073
      // marked, we need to dirty the entire array, not just its head.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1074
      if (is_obj_array) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1075
        // The [par_]mark_range() method expects mr.end() below to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1076
        // be aligned to the granularity of a bit's representation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1077
        // in the heap. In the case of the MUT below, that's a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1078
        // card size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1079
        MemRegion mr(start,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1080
                     (HeapWord*)round_to((intptr_t)(start + obj_size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1081
                        CardTableModRefBS::card_size /* bytes */));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1082
        if (par) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1083
          _modUnionTable.par_mark_range(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1084
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1085
          _modUnionTable.mark_range(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1086
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1087
      } else {  // not an obj array; we can just mark the head
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1088
        if (par) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1089
          _modUnionTable.par_mark(start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1090
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1091
          _modUnionTable.mark(start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1092
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1093
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1094
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1095
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1096
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1097
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1098
static inline size_t percent_of_space(Space* space, HeapWord* addr)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1099
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1100
  size_t delta = pointer_delta(addr, space->bottom());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1101
  return (size_t)(delta * 100.0 / (space->capacity() / HeapWordSize));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1102
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1103
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1104
void CMSCollector::icms_update_allocation_limits()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1105
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1106
  Generation* gen0 = GenCollectedHeap::heap()->get_gen(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1107
  EdenSpace* eden = gen0->as_DefNewGeneration()->eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1108
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1109
  const unsigned int duty_cycle = stats().icms_update_duty_cycle();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1110
  if (CMSTraceIncrementalPacing) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1111
    stats().print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1112
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1113
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1114
  assert(duty_cycle <= 100, "invalid duty cycle");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1115
  if (duty_cycle != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1116
    // The duty_cycle is a percentage between 0 and 100; convert to words and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1117
    // then compute the offset from the endpoints of the space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1118
    size_t free_words = eden->free() / HeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1119
    double free_words_dbl = (double)free_words;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1120
    size_t duty_cycle_words = (size_t)(free_words_dbl * duty_cycle / 100.0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1121
    size_t offset_words = (free_words - duty_cycle_words) / 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1122
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1123
    _icms_start_limit = eden->top() + offset_words;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1124
    _icms_stop_limit = eden->end() - offset_words;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1125
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1126
    // The limits may be adjusted (shifted to the right) by
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1127
    // CMSIncrementalOffset, to allow the application more mutator time after a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1128
    // young gen gc (when all mutators were stopped) and before CMS starts and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1129
    // takes away one or more cpus.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1130
    if (CMSIncrementalOffset != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1131
      double adjustment_dbl = free_words_dbl * CMSIncrementalOffset / 100.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1132
      size_t adjustment = (size_t)adjustment_dbl;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1133
      HeapWord* tmp_stop = _icms_stop_limit + adjustment;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1134
      if (tmp_stop > _icms_stop_limit && tmp_stop < eden->end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1135
        _icms_start_limit += adjustment;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1136
        _icms_stop_limit = tmp_stop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1137
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1138
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1139
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1140
  if (duty_cycle == 0 || (_icms_start_limit == _icms_stop_limit)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1141
    _icms_start_limit = _icms_stop_limit = eden->end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1142
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1143
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1144
  // Install the new start limit.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1145
  eden->set_soft_end(_icms_start_limit);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1146
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1147
  if (CMSTraceIncrementalMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1148
    gclog_or_tty->print(" icms alloc limits:  "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1149
                           PTR_FORMAT "," PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1150
                           " (" SIZE_FORMAT "%%," SIZE_FORMAT "%%) ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1151
                           _icms_start_limit, _icms_stop_limit,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1152
                           percent_of_space(eden, _icms_start_limit),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1153
                           percent_of_space(eden, _icms_stop_limit));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1154
    if (Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1155
      gclog_or_tty->print("eden:  ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1156
      eden->print_on(gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1157
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1158
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1159
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1160
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1161
// Any changes here should try to maintain the invariant
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1162
// that if this method is called with _icms_start_limit
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1163
// and _icms_stop_limit both NULL, then it should return NULL
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1164
// and not notify the icms thread.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1165
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1166
CMSCollector::allocation_limit_reached(Space* space, HeapWord* top,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1167
                                       size_t word_size)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1168
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1169
  // A start_limit equal to end() means the duty cycle is 0, so treat that as a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1170
  // nop.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1171
  if (CMSIncrementalMode && _icms_start_limit != space->end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1172
    if (top <= _icms_start_limit) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1173
      if (CMSTraceIncrementalMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1174
        space->print_on(gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1175
        gclog_or_tty->stamp();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1176
        gclog_or_tty->print_cr(" start limit top=" PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1177
                               ", new limit=" PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1178
                               " (" SIZE_FORMAT "%%)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1179
                               top, _icms_stop_limit,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1180
                               percent_of_space(space, _icms_stop_limit));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1181
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1182
      ConcurrentMarkSweepThread::start_icms();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1183
      assert(top < _icms_stop_limit, "Tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1184
      if (word_size < pointer_delta(_icms_stop_limit, top)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1185
        return _icms_stop_limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1186
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1187
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1188
      // The allocation will cross both the _start and _stop limits, so do the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1189
      // stop notification also and return end().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1190
      if (CMSTraceIncrementalMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1191
        space->print_on(gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1192
        gclog_or_tty->stamp();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1193
        gclog_or_tty->print_cr(" +stop limit top=" PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1194
                               ", new limit=" PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1195
                               " (" SIZE_FORMAT "%%)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1196
                               top, space->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1197
                               percent_of_space(space, space->end()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1198
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1199
      ConcurrentMarkSweepThread::stop_icms();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1200
      return space->end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1201
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1202
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1203
    if (top <= _icms_stop_limit) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1204
      if (CMSTraceIncrementalMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1205
        space->print_on(gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1206
        gclog_or_tty->stamp();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1207
        gclog_or_tty->print_cr(" stop limit top=" PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1208
                               ", new limit=" PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1209
                               " (" SIZE_FORMAT "%%)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1210
                               top, space->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1211
                               percent_of_space(space, space->end()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1212
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1213
      ConcurrentMarkSweepThread::stop_icms();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1214
      return space->end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1215
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1216
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1217
    if (CMSTraceIncrementalMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1218
      space->print_on(gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1219
      gclog_or_tty->stamp();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1220
      gclog_or_tty->print_cr(" end limit top=" PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1221
                             ", new limit=" PTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1222
                             top, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1223
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1224
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1225
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
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1229
oop ConcurrentMarkSweepGeneration::promote(oop obj, size_t obj_size, oop* ref) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1230
  assert(obj_size == (size_t)obj->size(), "bad obj_size passed in");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1231
  // allocate, copy and if necessary update promoinfo --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1232
  // delegate to underlying space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1233
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1234
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1235
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1236
  if (Universe::heap()->promotion_should_fail()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1237
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1238
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1239
#endif  // #ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1240
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1241
  oop res = _cmsSpace->promote(obj, obj_size, ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1242
  if (res == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1243
    // expand and retry
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1244
    size_t s = _cmsSpace->expansionSpaceRequired(obj_size);  // HeapWords
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1245
    expand(s*HeapWordSize, MinHeapDeltaBytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1246
      CMSExpansionCause::_satisfy_promotion);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1247
    // Since there's currently no next generation, we don't try to promote
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1248
    // into a more senior generation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1249
    assert(next_gen() == NULL, "assumption, based upon which no attempt "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1250
                               "is made to pass on a possibly failing "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1251
                               "promotion to next generation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1252
    res = _cmsSpace->promote(obj, obj_size, ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1253
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1254
  if (res != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1255
    // See comment in allocate() about when objects should
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1256
    // be allocated live.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1257
    assert(obj->is_oop(), "Will dereference klass pointer below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1258
    collector()->promoted(false,           // Not parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1259
                          (HeapWord*)res, obj->is_objArray(), obj_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1260
    // promotion counters
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1261
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1262
      _numObjectsPromoted++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1263
      _numWordsPromoted +=
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1264
        (int)(CompactibleFreeListSpace::adjustObjectSize(obj->size()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1265
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1266
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1267
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1268
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1269
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1270
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1271
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1272
ConcurrentMarkSweepGeneration::allocation_limit_reached(Space* space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1273
                                             HeapWord* top,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1274
                                             size_t word_sz)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1275
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1276
  return collector()->allocation_limit_reached(space, top, word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1277
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1278
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1279
// Things to support parallel young-gen collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1280
oop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1281
ConcurrentMarkSweepGeneration::par_promote(int thread_num,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1282
                                           oop old, markOop m,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1283
                                           size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1284
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1285
  if (Universe::heap()->promotion_should_fail()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1286
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1287
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1288
#endif  // #ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1289
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1290
  CMSParGCThreadState* ps = _par_gc_thread_states[thread_num];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1291
  PromotionInfo* promoInfo = &ps->promo;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1292
  // if we are tracking promotions, then first ensure space for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1293
  // promotion (including spooling space for saving header if necessary).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1294
  // then allocate and copy, then track promoted info if needed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1295
  // When tracking (see PromotionInfo::track()), the mark word may
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1296
  // be displaced and in this case restoration of the mark word
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1297
  // occurs in the (oop_since_save_marks_)iterate phase.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1298
  if (promoInfo->tracking() && !promoInfo->ensure_spooling_space()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1299
    // Out of space for allocating spooling buffers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1300
    // try expanding and allocating spooling buffers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1301
    if (!expand_and_ensure_spooling_space(promoInfo)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1302
      return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1303
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1304
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1305
  assert(promoInfo->has_spooling_space(), "Control point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1306
  HeapWord* obj_ptr = ps->lab.alloc(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1307
  if (obj_ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1308
     obj_ptr = expand_and_par_lab_allocate(ps, word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1309
     if (obj_ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1310
       return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1311
     }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1312
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1313
  oop obj = oop(obj_ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1314
  assert(obj->klass() == NULL, "Object should be uninitialized here.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1315
  // Otherwise, copy the object.  Here we must be careful to insert the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1316
  // klass pointer last, since this marks the block as an allocated object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1317
  HeapWord* old_ptr = (HeapWord*)old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1318
  if (word_sz > (size_t)oopDesc::header_size()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1319
    Copy::aligned_disjoint_words(old_ptr + oopDesc::header_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1320
                                 obj_ptr + oopDesc::header_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1321
                                 word_sz - oopDesc::header_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1322
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1323
  // Restore the mark word copied above.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1324
  obj->set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1325
  // Now we can track the promoted object, if necessary.  We take care
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1326
  // To delay the transition from uninitialized to full object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1327
  // (i.e., insertion of klass pointer) until after, so that it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1328
  // atomically becomes a promoted object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1329
  if (promoInfo->tracking()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1330
    promoInfo->track((PromotedObject*)obj, old->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1331
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1332
  // Finally, install the klass pointer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1333
  obj->set_klass(old->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1334
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1335
  assert(old->is_oop(), "Will dereference klass ptr below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1336
  collector()->promoted(true,          // parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1337
                        obj_ptr, old->is_objArray(), word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1338
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1339
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1340
    Atomic::inc(&_numObjectsPromoted);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1341
    Atomic::add((jint)CompactibleFreeListSpace::adjustObjectSize(obj->size()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1342
                &_numWordsPromoted);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1343
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1344
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1345
  return obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1346
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1347
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1348
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1349
ConcurrentMarkSweepGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1350
par_promote_alloc_undo(int thread_num,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1351
                       HeapWord* obj, size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1352
  // CMS does not support promotion undo.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1353
  ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1354
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1355
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1356
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1357
ConcurrentMarkSweepGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1358
par_promote_alloc_done(int thread_num) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1359
  CMSParGCThreadState* ps = _par_gc_thread_states[thread_num];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1360
  ps->lab.retire();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1361
#if CFLS_LAB_REFILL_STATS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1362
  if (thread_num == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1363
    _cmsSpace->print_par_alloc_stats();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1364
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1365
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1366
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1367
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1368
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1369
ConcurrentMarkSweepGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1370
par_oop_since_save_marks_iterate_done(int thread_num) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1371
  CMSParGCThreadState* ps = _par_gc_thread_states[thread_num];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1372
  ParScanWithoutBarrierClosure* dummy_cl = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1373
  ps->promo.promoted_oops_iterate_nv(dummy_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1374
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1375
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1376
// XXXPERM
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1377
bool ConcurrentMarkSweepGeneration::should_collect(bool   full,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1378
                                                   size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1379
                                                   bool   tlab)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1380
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1381
  // We allow a STW collection only if a full
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1382
  // collection was requested.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1383
  return full || should_allocate(size, tlab); // FIX ME !!!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1384
  // This and promotion failure handling are connected at the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1385
  // hip and should be fixed by untying them.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1386
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1387
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1388
bool CMSCollector::shouldConcurrentCollect() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1389
  if (_full_gc_requested) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1390
    assert(ExplicitGCInvokesConcurrent, "Unexpected state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1391
    if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1392
      gclog_or_tty->print_cr("CMSCollector: collect because of explicit "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1393
                             " gc request");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1394
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1395
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1396
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1397
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1398
  // For debugging purposes, change the type of collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1399
  // If the rotation is not on the concurrent collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1400
  // type, don't start a concurrent collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1401
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1402
    if (RotateCMSCollectionTypes &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1403
        (_cmsGen->debug_collection_type() !=
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1404
          ConcurrentMarkSweepGeneration::Concurrent_collection_type)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1405
      assert(_cmsGen->debug_collection_type() !=
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1406
        ConcurrentMarkSweepGeneration::Unknown_collection_type,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1407
        "Bad cms collection type");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1408
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1409
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1410
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1411
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1412
  FreelistLocker x(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1413
  // ------------------------------------------------------------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1414
  // Print out lots of information which affects the initiation of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1415
  // a collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1416
  if (PrintCMSInitiationStatistics && stats().valid()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1417
    gclog_or_tty->print("CMSCollector shouldConcurrentCollect: ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1418
    gclog_or_tty->stamp();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1419
    gclog_or_tty->print_cr("");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1420
    stats().print_on(gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1421
    gclog_or_tty->print_cr("time_until_cms_gen_full %3.7f",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1422
      stats().time_until_cms_gen_full());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1423
    gclog_or_tty->print_cr("free="SIZE_FORMAT, _cmsGen->free());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1424
    gclog_or_tty->print_cr("contiguous_available="SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1425
                           _cmsGen->contiguous_available());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1426
    gclog_or_tty->print_cr("promotion_rate=%g", stats().promotion_rate());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1427
    gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1428
    gclog_or_tty->print_cr("occupancy=%3.7f", _cmsGen->occupancy());
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1429
    gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy());
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1430
    gclog_or_tty->print_cr("initiatingPermOccupancy=%3.7f", _permGen->initiating_occupancy());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1431
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1432
  // ------------------------------------------------------------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1433
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1434
  // If the estimated time to complete a cms collection (cms_duration())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1435
  // is less than the estimated time remaining until the cms generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1436
  // is full, start a collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1437
  if (!UseCMSInitiatingOccupancyOnly) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1438
    if (stats().valid()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1439
      if (stats().time_until_cms_start() == 0.0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1440
        return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1441
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1442
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1443
      // We want to conservatively collect somewhat early in order
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1444
      // to try and "bootstrap" our CMS/promotion statistics;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1445
      // this branch will not fire after the first successful CMS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1446
      // collection because the stats should then be valid.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1447
      if (_cmsGen->occupancy() >= _bootstrap_occupancy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1448
        if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1449
          gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1450
            " CMSCollector: collect for bootstrapping statistics:"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1451
            " occupancy = %f, boot occupancy = %f", _cmsGen->occupancy(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1452
            _bootstrap_occupancy);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1453
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1454
        return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1455
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1456
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1457
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1458
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1459
  // Otherwise, we start a collection cycle if either the perm gen or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1460
  // old gen want a collection cycle started. Each may use
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1461
  // an appropriate criterion for making this decision.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1462
  // XXX We need to make sure that the gen expansion
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1463
  // criterion dovetails well with this. XXX NEED TO FIX THIS
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1464
  if (_cmsGen->should_concurrent_collect()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1465
    if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1466
      gclog_or_tty->print_cr("CMS old gen initiated");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1467
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1468
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1469
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1470
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1471
  // We start a collection if we believe an incremental collection may fail;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1472
  // this is not likely to be productive in practice because it's probably too
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1473
  // late anyway.
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1474
  GenCollectedHeap* gch = GenCollectedHeap::heap();
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1475
  assert(gch->collector_policy()->is_two_generation_policy(),
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1476
         "You may want to check the correctness of the following");
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1477
  if (gch->incremental_collection_will_fail()) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1478
    if (PrintGCDetails && Verbose) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1479
      gclog_or_tty->print("CMSCollector: collect because incremental collection will fail ");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1480
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1481
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1482
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1483
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1484
  if (CMSClassUnloadingEnabled && _permGen->should_concurrent_collect()) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1485
    bool res = update_should_unload_classes();
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1486
    if (res) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1487
      if (Verbose && PrintGCDetails) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1488
        gclog_or_tty->print_cr("CMS perm gen initiated");
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1489
      }
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1490
      return true;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1491
    }
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1492
  }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1493
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1494
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1495
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1496
// Clear _expansion_cause fields of constituent generations
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1497
void CMSCollector::clear_expansion_cause() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1498
  _cmsGen->clear_expansion_cause();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1499
  _permGen->clear_expansion_cause();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1500
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1501
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1502
// We should be conservative in starting a collection cycle.  To
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1503
// start too eagerly runs the risk of collecting too often in the
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1504
// extreme.  To collect too rarely falls back on full collections,
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1505
// which works, even if not optimum in terms of concurrent work.
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1506
// As a work around for too eagerly collecting, use the flag
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1507
// UseCMSInitiatingOccupancyOnly.  This also has the advantage of
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1508
// giving the user an easily understandable way of controlling the
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1509
// collections.
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1510
// We want to start a new collection cycle if any of the following
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1511
// conditions hold:
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1512
// . our current occupancy exceeds the configured initiating occupancy
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1513
//   for this generation, or
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1514
// . we recently needed to expand this space and have not, since that
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1515
//   expansion, done a collection of this generation, or
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1516
// . the underlying space believes that it may be a good idea to initiate
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1517
//   a concurrent collection (this may be based on criteria such as the
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1518
//   following: the space uses linear allocation and linear allocation is
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1519
//   going to fail, or there is believed to be excessive fragmentation in
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1520
//   the generation, etc... or ...
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1521
// [.(currently done by CMSCollector::shouldConcurrentCollect() only for
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1522
//   the case of the old generation, not the perm generation; see CR 6543076):
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1523
//   we may be approaching a point at which allocation requests may fail because
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1524
//   we will be out of sufficient free space given allocation rate estimates.]
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1525
bool ConcurrentMarkSweepGeneration::should_concurrent_collect() const {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1526
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1527
  assert_lock_strong(freelistLock());
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1528
  if (occupancy() > initiating_occupancy()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1529
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1530
      gclog_or_tty->print(" %s: collect because of occupancy %f / %f  ",
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1531
        short_name(), occupancy(), initiating_occupancy());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1532
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1533
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1534
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1535
  if (UseCMSInitiatingOccupancyOnly) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1536
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1537
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1538
  if (expansion_cause() == CMSExpansionCause::_satisfy_allocation) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1539
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1540
      gclog_or_tty->print(" %s: collect because expanded for allocation ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1541
        short_name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1542
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1543
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1544
  }
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1545
  if (_cmsSpace->should_concurrent_collect()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1546
    if (PrintGCDetails && Verbose) {
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1547
      gclog_or_tty->print(" %s: collect because cmsSpace says so ",
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1548
        short_name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1549
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1550
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1551
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1552
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1553
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1554
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1555
void ConcurrentMarkSweepGeneration::collect(bool   full,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1556
                                            bool   clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1557
                                            size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1558
                                            bool   tlab)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1559
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1560
  collector()->collect(full, clear_all_soft_refs, size, tlab);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1561
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1562
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1563
void CMSCollector::collect(bool   full,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1564
                           bool   clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1565
                           size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1566
                           bool   tlab)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1567
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1568
  if (!UseCMSCollectionPassing && _collectorState > Idling) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1569
    // For debugging purposes skip the collection if the state
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1570
    // is not currently idle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1571
    if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1572
      gclog_or_tty->print_cr("Thread " INTPTR_FORMAT " skipped full:%d CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1573
        Thread::current(), full, _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1574
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1575
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1576
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1577
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1578
  // The following "if" branch is present for defensive reasons.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1579
  // In the current uses of this interface, it can be replaced with:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1580
  // assert(!GC_locker.is_active(), "Can't be called otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1581
  // But I am not placing that assert here to allow future
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1582
  // generality in invoking this interface.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1583
  if (GC_locker::is_active()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1584
    // A consistency test for GC_locker
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1585
    assert(GC_locker::needs_gc(), "Should have been set already");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1586
    // Skip this foreground collection, instead
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1587
    // expanding the heap if necessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1588
    // Need the free list locks for the call to free() in compute_new_size()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1589
    compute_new_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1590
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1591
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1592
  acquire_control_and_collect(full, clear_all_soft_refs);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1593
  _full_gcs_since_conc_gc++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1594
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1595
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1596
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1597
void CMSCollector::request_full_gc(unsigned int full_gc_count) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1598
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1599
  unsigned int gc_count = gch->total_full_collections();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1600
  if (gc_count == full_gc_count) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1601
    MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1602
    _full_gc_requested = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1603
    CGC_lock->notify();   // nudge CMS thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1604
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1605
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1606
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1607
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1608
// The foreground and background collectors need to coordinate in order
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1609
// to make sure that they do not mutually interfere with CMS collections.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1610
// When a background collection is active,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1611
// the foreground collector may need to take over (preempt) and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1612
// synchronously complete an ongoing collection. Depending on the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1613
// frequency of the background collections and the heap usage
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1614
// of the application, this preemption can be seldom or frequent.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1615
// There are only certain
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1616
// points in the background collection that the "collection-baton"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1617
// can be passed to the foreground collector.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1618
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1619
// The foreground collector will wait for the baton before
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1620
// starting any part of the collection.  The foreground collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1621
// will only wait at one location.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1622
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1623
// The background collector will yield the baton before starting a new
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1624
// phase of the collection (e.g., before initial marking, marking from roots,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1625
// precleaning, final re-mark, sweep etc.)  This is normally done at the head
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1626
// of the loop which switches the phases. The background collector does some
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1627
// of the phases (initial mark, final re-mark) with the world stopped.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1628
// Because of locking involved in stopping the world,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1629
// the foreground collector should not block waiting for the background
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1630
// collector when it is doing a stop-the-world phase.  The background
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1631
// collector will yield the baton at an additional point just before
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1632
// it enters a stop-the-world phase.  Once the world is stopped, the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1633
// background collector checks the phase of the collection.  If the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1634
// phase has not changed, it proceeds with the collection.  If the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1635
// phase has changed, it skips that phase of the collection.  See
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1636
// the comments on the use of the Heap_lock in collect_in_background().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1637
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1638
// Variable used in baton passing.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1639
//   _foregroundGCIsActive - Set to true by the foreground collector when
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1640
//      it wants the baton.  The foreground clears it when it has finished
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1641
//      the collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1642
//   _foregroundGCShouldWait - Set to true by the background collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1643
//        when it is running.  The foreground collector waits while
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1644
//      _foregroundGCShouldWait is true.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1645
//  CGC_lock - monitor used to protect access to the above variables
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1646
//      and to notify the foreground and background collectors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1647
//  _collectorState - current state of the CMS collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1648
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1649
// The foreground collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1650
//   acquires the CGC_lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1651
//   sets _foregroundGCIsActive
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1652
//   waits on the CGC_lock for _foregroundGCShouldWait to be false
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1653
//     various locks acquired in preparation for the collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1654
//     are released so as not to block the background collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1655
//     that is in the midst of a collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1656
//   proceeds with the collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1657
//   clears _foregroundGCIsActive
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1658
//   returns
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1659
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1660
// The background collector in a loop iterating on the phases of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1661
//      collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1662
//   acquires the CGC_lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1663
//   sets _foregroundGCShouldWait
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1664
//   if _foregroundGCIsActive is set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1665
//     clears _foregroundGCShouldWait, notifies _CGC_lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1666
//     waits on _CGC_lock for _foregroundGCIsActive to become false
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1667
//     and exits the loop.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1668
//   otherwise
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1669
//     proceed with that phase of the collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1670
//     if the phase is a stop-the-world phase,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1671
//       yield the baton once more just before enqueueing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1672
//       the stop-world CMS operation (executed by the VM thread).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1673
//   returns after all phases of the collection are done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1674
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1675
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1676
void CMSCollector::acquire_control_and_collect(bool full,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1677
        bool clear_all_soft_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1678
  assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1679
  assert(!Thread::current()->is_ConcurrentGC_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1680
         "shouldn't try to acquire control from self!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1681
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1682
  // Start the protocol for acquiring control of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1683
  // collection from the background collector (aka CMS thread).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1684
  assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1685
         "VM thread should have CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1686
  // Remember the possibly interrupted state of an ongoing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1687
  // concurrent collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1688
  CollectorState first_state = _collectorState;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1689
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1690
  // Signal to a possibly ongoing concurrent collection that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1691
  // we want to do a foreground collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1692
  _foregroundGCIsActive = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1693
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1694
  // Disable incremental mode during a foreground collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1695
  ICMSDisabler icms_disabler;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1696
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1697
  // release locks and wait for a notify from the background collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1698
  // releasing the locks in only necessary for phases which
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1699
  // do yields to improve the granularity of the collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1700
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1701
  // We need to lock the Free list lock for the space that we are
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1702
  // currently collecting.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1703
  assert(haveFreelistLocks(), "Must be holding free list locks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1704
  bitMapLock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1705
  releaseFreelistLocks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1706
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1707
    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1708
    if (_foregroundGCShouldWait) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1709
      // We are going to be waiting for action for the CMS thread;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1710
      // it had better not be gone (for instance at shutdown)!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1711
      assert(ConcurrentMarkSweepThread::cmst() != NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1712
             "CMS thread must be running");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1713
      // Wait here until the background collector gives us the go-ahead
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1714
      ConcurrentMarkSweepThread::clear_CMS_flag(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1715
        ConcurrentMarkSweepThread::CMS_vm_has_token);  // release token
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1716
      // Get a possibly blocked CMS thread going:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1717
      //   Note that we set _foregroundGCIsActive true above,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1718
      //   without protection of the CGC_lock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1719
      CGC_lock->notify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1720
      assert(!ConcurrentMarkSweepThread::vm_thread_wants_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1721
             "Possible deadlock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1722
      while (_foregroundGCShouldWait) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1723
        // wait for notification
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1724
        CGC_lock->wait(Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1725
        // Possibility of delay/starvation here, since CMS token does
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1726
        // not know to give priority to VM thread? Actually, i think
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1727
        // there wouldn't be any delay/starvation, but the proof of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1728
        // that "fact" (?) appears non-trivial. XXX 20011219YSR
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1729
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1730
      ConcurrentMarkSweepThread::set_CMS_flag(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1731
        ConcurrentMarkSweepThread::CMS_vm_has_token);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1732
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1733
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1734
  // The CMS_token is already held.  Get back the other locks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1735
  assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1736
         "VM thread should have CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1737
  getFreelistLocks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1738
  bitMapLock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1739
  if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1740
    gclog_or_tty->print_cr("CMS foreground collector has asked for control "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1741
      INTPTR_FORMAT " with first state %d", Thread::current(), first_state);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1742
    gclog_or_tty->print_cr("    gets control with state %d", _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1743
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1744
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1745
  // Check if we need to do a compaction, or if not, whether
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1746
  // we need to start the mark-sweep from scratch.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1747
  bool should_compact    = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1748
  bool should_start_over = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1749
  decide_foreground_collection_type(clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1750
    &should_compact, &should_start_over);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1751
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1752
NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1753
  if (RotateCMSCollectionTypes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1754
    if (_cmsGen->debug_collection_type() ==
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1755
        ConcurrentMarkSweepGeneration::MSC_foreground_collection_type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1756
      should_compact = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1757
    } else if (_cmsGen->debug_collection_type() ==
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1758
               ConcurrentMarkSweepGeneration::MS_foreground_collection_type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1759
      should_compact = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1760
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1761
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1762
)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1763
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1764
  if (PrintGCDetails && first_state > Idling) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1765
    GCCause::Cause cause = GenCollectedHeap::heap()->gc_cause();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1766
    if (GCCause::is_user_requested_gc(cause) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1767
        GCCause::is_serviceability_requested_gc(cause)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1768
      gclog_or_tty->print(" (concurrent mode interrupted)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1769
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1770
      gclog_or_tty->print(" (concurrent mode failure)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1771
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1772
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1773
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1774
  if (should_compact) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1775
    // If the collection is being acquired from the background
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1776
    // collector, there may be references on the discovered
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1777
    // references lists that have NULL referents (being those
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1778
    // that were concurrently cleared by a mutator) or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1779
    // that are no longer active (having been enqueued concurrently
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1780
    // by the mutator).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1781
    // Scrub the list of those references because Mark-Sweep-Compact
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1782
    // code assumes referents are not NULL and that all discovered
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1783
    // Reference objects are active.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1784
    ref_processor()->clean_up_discovered_references();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1785
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1786
    do_compaction_work(clear_all_soft_refs);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1787
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1788
    // Has the GC time limit been exceeded?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1789
    check_gc_time_limit();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1790
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1791
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1792
    do_mark_sweep_work(clear_all_soft_refs, first_state,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1793
      should_start_over);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1794
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1795
  // Reset the expansion cause, now that we just completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1796
  // a collection cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1797
  clear_expansion_cause();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1798
  _foregroundGCIsActive = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1799
  return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1800
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1801
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1802
void CMSCollector::check_gc_time_limit() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1803
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1804
  // Ignore explicit GC's.  Exiting here does not set the flag and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1805
  // does not reset the count.  Updating of the averages for system
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1806
  // GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1807
  GCCause::Cause gc_cause = GenCollectedHeap::heap()->gc_cause();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1808
  if (GCCause::is_user_requested_gc(gc_cause) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1809
      GCCause::is_serviceability_requested_gc(gc_cause)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1810
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1811
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1812
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1813
  // Calculate the fraction of the CMS generation was freed during
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1814
  // the last collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1815
  // Only consider the STW compacting cost for now.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1816
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1817
  // Note that the gc time limit test only works for the collections
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1818
  // of the young gen + tenured gen and not for collections of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1819
  // permanent gen.  That is because the calculation of the space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1820
  // freed by the collection is the free space in the young gen +
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1821
  // tenured gen.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1822
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1823
  double fraction_free =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1824
    ((double)_cmsGen->free())/((double)_cmsGen->max_capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1825
  if ((100.0 * size_policy()->compacting_gc_cost()) >
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1826
         ((double) GCTimeLimit) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1827
        ((fraction_free * 100) < GCHeapFreeLimit)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1828
    size_policy()->inc_gc_time_limit_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1829
    if (UseGCOverheadLimit &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1830
        (size_policy()->gc_time_limit_count() >
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1831
         AdaptiveSizePolicyGCTimeLimitThreshold)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1832
      size_policy()->set_gc_time_limit_exceeded(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1833
      // Avoid consecutive OOM due to the gc time limit by resetting
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1834
      // the counter.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1835
      size_policy()->reset_gc_time_limit_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1836
      if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1837
        gclog_or_tty->print_cr("      GC is exceeding overhead limit "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1838
          "of %d%%", GCTimeLimit);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1839
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1840
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1841
      if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1842
        gclog_or_tty->print_cr("      GC would exceed overhead limit "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1843
          "of %d%%", GCTimeLimit);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1844
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1845
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1846
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1847
    size_policy()->reset_gc_time_limit_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1848
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1849
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1850
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1851
// Resize the perm generation and the tenured generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1852
// after obtaining the free list locks for the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1853
// two generations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1854
void CMSCollector::compute_new_size() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1855
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1856
  FreelistLocker z(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1857
  _permGen->compute_new_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1858
  _cmsGen->compute_new_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1859
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1860
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1861
// A work method used by foreground collection to determine
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1862
// what type of collection (compacting or not, continuing or fresh)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1863
// it should do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1864
// NOTE: the intent is to make UseCMSCompactAtFullCollection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1865
// and CMSCompactWhenClearAllSoftRefs the default in the future
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1866
// and do away with the flags after a suitable period.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1867
void CMSCollector::decide_foreground_collection_type(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1868
  bool clear_all_soft_refs, bool* should_compact,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1869
  bool* should_start_over) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1870
  // Normally, we'll compact only if the UseCMSCompactAtFullCollection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1871
  // flag is set, and we have either requested a System.gc() or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1872
  // the number of full gc's since the last concurrent cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1873
  // has exceeded the threshold set by CMSFullGCsBeforeCompaction,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1874
  // or if an incremental collection has failed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1875
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1876
  assert(gch->collector_policy()->is_two_generation_policy(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1877
         "You may want to check the correctness of the following");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1878
  // Inform cms gen if this was due to partial collection failing.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1879
  // The CMS gen may use this fact to determine its expansion policy.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1880
  if (gch->incremental_collection_will_fail()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1881
    assert(!_cmsGen->incremental_collection_failed(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1882
           "Should have been noticed, reacted to and cleared");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1883
    _cmsGen->set_incremental_collection_failed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1884
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1885
  *should_compact =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1886
    UseCMSCompactAtFullCollection &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1887
    ((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1888
     GCCause::is_user_requested_gc(gch->gc_cause()) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1889
     gch->incremental_collection_will_fail());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1890
  *should_start_over = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1891
  if (clear_all_soft_refs && !*should_compact) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1892
    // We are about to do a last ditch collection attempt
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1893
    // so it would normally make sense to do a compaction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1894
    // to reclaim as much space as possible.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1895
    if (CMSCompactWhenClearAllSoftRefs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1896
      // Default: The rationale is that in this case either
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1897
      // we are past the final marking phase, in which case
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1898
      // we'd have to start over, or so little has been done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1899
      // that there's little point in saving that work. Compaction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1900
      // appears to be the sensible choice in either case.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1901
      *should_compact = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1902
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1903
      // We have been asked to clear all soft refs, but not to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1904
      // compact. Make sure that we aren't past the final checkpoint
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1905
      // phase, for that is where we process soft refs. If we are already
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1906
      // past that phase, we'll need to redo the refs discovery phase and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1907
      // if necessary clear soft refs that weren't previously
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1908
      // cleared. We do so by remembering the phase in which
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1909
      // we came in, and if we are past the refs processing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1910
      // phase, we'll choose to just redo the mark-sweep
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1911
      // collection from scratch.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1912
      if (_collectorState > FinalMarking) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1913
        // We are past the refs processing phase;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1914
        // start over and do a fresh synchronous CMS cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1915
        _collectorState = Resetting; // skip to reset to start new cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1916
        reset(false /* == !asynch */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1917
        *should_start_over = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1918
      } // else we can continue a possibly ongoing current cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1919
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1920
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1921
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1922
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1923
// A work method used by the foreground collector to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1924
// a mark-sweep-compact.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1925
void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1926
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1927
  TraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1928
  if (PrintGC && Verbose && !(GCCause::is_user_requested_gc(gch->gc_cause()))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1929
    gclog_or_tty->print_cr("Compact ConcurrentMarkSweepGeneration after %d "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1930
      "collections passed to foreground collector", _full_gcs_since_conc_gc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1931
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1932
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1933
  // Sample collection interval time and reset for collection pause.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1934
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1935
    size_policy()->msc_collection_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1936
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1937
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1938
  // Temporarily widen the span of the weak reference processing to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1939
  // the entire heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1940
  MemRegion new_span(GenCollectedHeap::heap()->reserved_region());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1941
  ReferenceProcessorSpanMutator x(ref_processor(), new_span);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1942
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1943
  // Temporarily, clear the "is_alive_non_header" field of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1944
  // reference processor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1945
  ReferenceProcessorIsAliveMutator y(ref_processor(), NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1946
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1947
  // Temporarily make reference _processing_ single threaded (non-MT).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1948
  ReferenceProcessorMTProcMutator z(ref_processor(), false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1949
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1950
  // Temporarily make refs discovery atomic
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1951
  ReferenceProcessorAtomicMutator w(ref_processor(), true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1952
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1953
  ref_processor()->set_enqueuing_is_done(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1954
  ref_processor()->enable_discovery();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1955
  // If an asynchronous collection finishes, the _modUnionTable is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1956
  // all clear.  If we are assuming the collection from an asynchronous
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1957
  // collection, clear the _modUnionTable.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1958
  assert(_collectorState != Idling || _modUnionTable.isAllClear(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1959
    "_modUnionTable should be clear if the baton was not passed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1960
  _modUnionTable.clear_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1961
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1962
  // We must adjust the allocation statistics being maintained
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1963
  // in the free list space. We do so by reading and clearing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1964
  // the sweep timer and updating the block flux rate estimates below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1965
  assert(_sweep_timer.is_active(), "We should never see the timer inactive");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1966
  _sweep_timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1967
  // Note that we do not use this sample to update the _sweep_estimate.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1968
  _cmsGen->cmsSpace()->beginSweepFLCensus((float)(_sweep_timer.seconds()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1969
                                          _sweep_estimate.padded_average());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1970
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1971
  GenMarkSweep::invoke_at_safepoint(_cmsGen->level(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1972
    ref_processor(), clear_all_soft_refs);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1973
  #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1974
    CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1975
    size_t free_size = cms_space->free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1976
    assert(free_size ==
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1977
           pointer_delta(cms_space->end(), cms_space->compaction_top())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1978
           * HeapWordSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1979
      "All the free space should be compacted into one chunk at top");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1980
    assert(cms_space->dictionary()->totalChunkSize(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1981
                                      debug_only(cms_space->freelistLock())) == 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1982
           cms_space->totalSizeInIndexedFreeLists() == 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1983
      "All the free space should be in a single chunk");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1984
    size_t num = cms_space->totalCount();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1985
    assert((free_size == 0 && num == 0) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1986
           (free_size > 0  && (num == 1 || num == 2)),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1987
         "There should be at most 2 free chunks after compaction");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1988
  #endif // ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1989
  _collectorState = Resetting;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1990
  assert(_restart_addr == NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1991
         "Should have been NULL'd before baton was passed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1992
  reset(false /* == !asynch */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1993
  _cmsGen->reset_after_compaction();
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1994
  _concurrent_cycles_since_last_unload = 0;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1995
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  1996
  if (verifying() && !should_unload_classes()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1997
    perm_gen_verify_bit_map()->clear_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1998
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1999
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2000
  // Clear any data recorded in the PLAB chunk arrays.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2001
  if (_survivor_plab_array != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2002
    reset_survivor_plab_arrays();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2003
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2004
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2005
  // Adjust the per-size allocation stats for the next epoch.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2006
  _cmsGen->cmsSpace()->endSweepFLCensus(sweepCount() /* fake */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2007
  // Restart the "sweep timer" for next epoch.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2008
  _sweep_timer.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2009
  _sweep_timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2010
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2011
  // Sample collection pause time and reset for collection interval.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2012
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2013
    size_policy()->msc_collection_end(gch->gc_cause());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2014
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2015
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2016
  // For a mark-sweep-compact, compute_new_size() will be called
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2017
  // in the heap's do_collection() method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2018
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2019
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2020
// A work method used by the foreground collector to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2021
// a mark-sweep, after taking over from a possibly on-going
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2022
// concurrent mark-sweep collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2023
void CMSCollector::do_mark_sweep_work(bool clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2024
  CollectorState first_state, bool should_start_over) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2025
  if (PrintGC && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2026
    gclog_or_tty->print_cr("Pass concurrent collection to foreground "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2027
      "collector with count %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2028
      _full_gcs_since_conc_gc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2029
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2030
  switch (_collectorState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2031
    case Idling:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2032
      if (first_state == Idling || should_start_over) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2033
        // The background GC was not active, or should
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2034
        // restarted from scratch;  start the cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2035
        _collectorState = InitialMarking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2036
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2037
      // If first_state was not Idling, then a background GC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2038
      // was in progress and has now finished.  No need to do it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2039
      // again.  Leave the state as Idling.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2040
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2041
    case Precleaning:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2042
      // In the foreground case don't do the precleaning since
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2043
      // it is not done concurrently and there is extra work
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2044
      // required.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2045
      _collectorState = FinalMarking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2046
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2047
  if (PrintGCDetails &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2048
      (_collectorState > Idling ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2049
       !GCCause::is_user_requested_gc(GenCollectedHeap::heap()->gc_cause()))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2050
    gclog_or_tty->print(" (concurrent mode failure)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2051
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2052
  collect_in_foreground(clear_all_soft_refs);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2053
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2054
  // For a mark-sweep, compute_new_size() will be called
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2055
  // in the heap's do_collection() method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2056
}
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 CMSCollector::getFreelistLocks() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2060
  // Get locks for all free lists in all generations that this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2061
  // collector is responsible for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2062
  _cmsGen->freelistLock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2063
  _permGen->freelistLock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2064
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2065
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2066
void CMSCollector::releaseFreelistLocks() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2067
  // Release locks for all free lists in all generations that this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2068
  // collector is responsible for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2069
  _cmsGen->freelistLock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2070
  _permGen->freelistLock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2071
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2072
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2073
bool CMSCollector::haveFreelistLocks() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2074
  // Check locks for all free lists in all generations that this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2075
  // collector is responsible for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2076
  assert_lock_strong(_cmsGen->freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2077
  assert_lock_strong(_permGen->freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2078
  PRODUCT_ONLY(ShouldNotReachHere());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2079
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2080
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2081
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2082
// A utility class that is used by the CMS collector to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2083
// temporarily "release" the foreground collector from its
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2084
// usual obligation to wait for the background collector to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2085
// complete an ongoing phase before proceeding.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2086
class ReleaseForegroundGC: public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2087
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2088
  CMSCollector* _c;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2089
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2090
  ReleaseForegroundGC(CMSCollector* c) : _c(c) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2091
    assert(_c->_foregroundGCShouldWait, "Else should not need to call");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2092
    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2093
    // allow a potentially blocked foreground collector to proceed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2094
    _c->_foregroundGCShouldWait = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2095
    if (_c->_foregroundGCIsActive) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2096
      CGC_lock->notify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2097
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2098
    assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2099
           "Possible deadlock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2100
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2101
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2102
  ~ReleaseForegroundGC() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2103
    assert(!_c->_foregroundGCShouldWait, "Usage protocol violation?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2104
    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2105
    _c->_foregroundGCShouldWait = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2106
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2107
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2108
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2109
// There are separate collect_in_background and collect_in_foreground because of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2110
// the different locking requirements of the background collector and the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2111
// foreground collector.  There was originally an attempt to share
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2112
// one "collect" method between the background collector and the foreground
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2113
// collector but the if-then-else required made it cleaner to have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2114
// separate methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2115
void CMSCollector::collect_in_background(bool clear_all_soft_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2116
  assert(Thread::current()->is_ConcurrentGC_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2117
    "A CMS asynchronous collection is only allowed on a CMS thread.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2118
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2119
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2120
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2121
    bool safepoint_check = Mutex::_no_safepoint_check_flag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2122
    MutexLockerEx hl(Heap_lock, safepoint_check);
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  2123
    FreelistLocker fll(this);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2124
    MutexLockerEx x(CGC_lock, safepoint_check);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2125
    if (_foregroundGCIsActive || !UseAsyncConcMarkSweepGC) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2126
      // The foreground collector is active or we're
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2127
      // not using asynchronous collections.  Skip this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2128
      // background collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2129
      assert(!_foregroundGCShouldWait, "Should be clear");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2130
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2131
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2132
      assert(_collectorState == Idling, "Should be idling before start.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2133
      _collectorState = InitialMarking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2134
      // Reset the expansion cause, now that we are about to begin
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2135
      // a new cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2136
      clear_expansion_cause();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2137
    }
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  2138
    // Decide if we want to enable class unloading as part of the
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  2139
    // ensuing concurrent GC cycle.
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  2140
    update_should_unload_classes();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2141
    _full_gc_requested = false;           // acks all outstanding full gc requests
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2142
    // Signal that we are about to start a collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2143
    gch->increment_total_full_collections();  // ... starting a collection cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2144
    _collection_count_start = gch->total_full_collections();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2145
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2146
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2147
  // Used for PrintGC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2148
  size_t prev_used;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2149
  if (PrintGC && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2150
    prev_used = _cmsGen->used(); // XXXPERM
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2151
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2152
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2153
  // The change of the collection state is normally done at this level;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2154
  // the exceptions are phases that are executed while the world is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2155
  // stopped.  For those phases the change of state is done while the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2156
  // world is stopped.  For baton passing purposes this allows the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2157
  // background collector to finish the phase and change state atomically.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2158
  // The foreground collector cannot wait on a phase that is done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2159
  // while the world is stopped because the foreground collector already
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2160
  // has the world stopped and would deadlock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2161
  while (_collectorState != Idling) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2162
    if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2163
      gclog_or_tty->print_cr("Thread " INTPTR_FORMAT " in CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2164
        Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2165
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2166
    // The foreground collector
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2167
    //   holds the Heap_lock throughout its collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2168
    //   holds the CMS token (but not the lock)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2169
    //     except while it is waiting for the background collector to yield.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2170
    //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2171
    // The foreground collector should be blocked (not for long)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2172
    //   if the background collector is about to start a phase
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2173
    //   executed with world stopped.  If the background
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2174
    //   collector has already started such a phase, the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2175
    //   foreground collector is blocked waiting for the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2176
    //   Heap_lock.  The stop-world phases (InitialMarking and FinalMarking)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2177
    //   are executed in the VM thread.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2178
    //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2179
    // The locking order is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2180
    //   PendingListLock (PLL)  -- if applicable (FinalMarking)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2181
    //   Heap_lock  (both this & PLL locked in VM_CMS_Operation::prologue())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2182
    //   CMS token  (claimed in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2183
    //                stop_world_and_do() -->
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2184
    //                  safepoint_synchronize() -->
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2185
    //                    CMSThread::synchronize())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2186
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2187
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2188
      // Check if the FG collector wants us to yield.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2189
      CMSTokenSync x(true); // is cms thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2190
      if (waitForForegroundGC()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2191
        // We yielded to a foreground GC, nothing more to be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2192
        // done this round.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2193
        assert(_foregroundGCShouldWait == false, "We set it to false in "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2194
               "waitForForegroundGC()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2195
        if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2196
          gclog_or_tty->print_cr("CMS Thread " INTPTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2197
            " exiting collection CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2198
            Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2199
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2200
        return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2201
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2202
        // The background collector can run but check to see if the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2203
        // foreground collector has done a collection while the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2204
        // background collector was waiting to get the CGC_lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2205
        // above.  If yes, break so that _foregroundGCShouldWait
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2206
        // is cleared before returning.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2207
        if (_collectorState == Idling) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2208
          break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2209
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2210
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2211
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2212
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2213
    assert(_foregroundGCShouldWait, "Foreground collector, if active, "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2214
      "should be waiting");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2215
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2216
    switch (_collectorState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2217
      case InitialMarking:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2218
        {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2219
          ReleaseForegroundGC x(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2220
          stats().record_cms_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2221
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2222
          VM_CMS_Initial_Mark initial_mark_op(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2223
          VMThread::execute(&initial_mark_op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2224
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2225
        // The collector state may be any legal state at this point
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2226
        // since the background collector may have yielded to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2227
        // foreground collector.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2228
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2229
      case Marking:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2230
        // initial marking in checkpointRootsInitialWork has been completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2231
        if (markFromRoots(true)) { // we were successful
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2232
          assert(_collectorState == Precleaning, "Collector state should "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2233
            "have changed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2234
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2235
          assert(_foregroundGCIsActive, "Internal state inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2236
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2237
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2238
      case Precleaning:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2239
        if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2240
          size_policy()->concurrent_precleaning_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2241
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2242
        // marking from roots in markFromRoots has been completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2243
        preclean();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2244
        if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2245
          size_policy()->concurrent_precleaning_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2246
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2247
        assert(_collectorState == AbortablePreclean ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2248
               _collectorState == FinalMarking,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2249
               "Collector state should have changed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2250
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2251
      case AbortablePreclean:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2252
        if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2253
        size_policy()->concurrent_phases_resume();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2254
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2255
        abortable_preclean();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2256
        if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2257
          size_policy()->concurrent_precleaning_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2258
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2259
        assert(_collectorState == FinalMarking, "Collector state should "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2260
          "have changed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2261
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2262
      case FinalMarking:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2263
        {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2264
          ReleaseForegroundGC x(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2265
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2266
          VM_CMS_Final_Remark final_remark_op(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2267
          VMThread::execute(&final_remark_op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2268
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2269
        assert(_foregroundGCShouldWait, "block post-condition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2270
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2271
      case Sweeping:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2272
        if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2273
          size_policy()->concurrent_sweeping_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2274
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2275
        // final marking in checkpointRootsFinal has been completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2276
        sweep(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2277
        assert(_collectorState == Resizing, "Collector state change "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2278
          "to Resizing must be done under the free_list_lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2279
        _full_gcs_since_conc_gc = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2280
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2281
        // Stop the timers for adaptive size policy for the concurrent phases
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2282
        if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2283
          size_policy()->concurrent_sweeping_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2284
          size_policy()->concurrent_phases_end(gch->gc_cause(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2285
                                             gch->prev_gen(_cmsGen)->capacity(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2286
                                             _cmsGen->free());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2287
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2288
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2289
      case Resizing: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2290
        // Sweeping has been completed...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2291
        // At this point the background collection has completed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2292
        // Don't move the call to compute_new_size() down
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2293
        // into code that might be executed if the background
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2294
        // collection was preempted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2295
        {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2296
          ReleaseForegroundGC x(this);   // unblock FG collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2297
          MutexLockerEx       y(Heap_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2298
          CMSTokenSync        z(true);   // not strictly needed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2299
          if (_collectorState == Resizing) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2300
            compute_new_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2301
            _collectorState = Resetting;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2302
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2303
            assert(_collectorState == Idling, "The state should only change"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2304
                   " because the foreground collector has finished the collection");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2305
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2306
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2307
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2308
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2309
      case Resetting:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2310
        // CMS heap resizing has been completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2311
        reset(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2312
        assert(_collectorState == Idling, "Collector state should "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2313
          "have changed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2314
        stats().record_cms_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2315
        // Don't move the concurrent_phases_end() and compute_new_size()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2316
        // calls to here because a preempted background collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2317
        // has it's state set to "Resetting".
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2318
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2319
      case Idling:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2320
      default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2321
        ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2322
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2323
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2324
    if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2325
      gclog_or_tty->print_cr("  Thread " INTPTR_FORMAT " done - next CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2326
        Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2327
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2328
    assert(_foregroundGCShouldWait, "block post-condition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2329
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2330
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2331
  // Should this be in gc_epilogue?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2332
  collector_policy()->counters()->update_counters();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2333
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2334
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2335
    // Clear _foregroundGCShouldWait and, in the event that the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2336
    // foreground collector is waiting, notify it, before
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2337
    // returning.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2338
    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2339
    _foregroundGCShouldWait = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2340
    if (_foregroundGCIsActive) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2341
      CGC_lock->notify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2342
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2343
    assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2344
           "Possible deadlock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2345
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2346
  if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2347
    gclog_or_tty->print_cr("CMS Thread " INTPTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2348
      " exiting collection CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2349
      Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2350
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2351
  if (PrintGC && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2352
    _cmsGen->print_heap_change(prev_used);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2353
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2354
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2355
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2356
void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2357
  assert(_foregroundGCIsActive && !_foregroundGCShouldWait,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2358
         "Foreground collector should be waiting, not executing");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2359
  assert(Thread::current()->is_VM_thread(), "A foreground collection"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2360
    "may only be done by the VM Thread with the world stopped");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2361
  assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2362
         "VM thread should have CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2363
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2364
  NOT_PRODUCT(TraceTime t("CMS:MS (foreground) ", PrintGCDetails && Verbose,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2365
    true, gclog_or_tty);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2366
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2367
    size_policy()->ms_collection_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2368
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2369
  COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2370
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2371
  HandleMark hm;  // Discard invalid handles created during verification
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2372
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2373
  if (VerifyBeforeGC &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2374
      GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2375
    Universe::verify(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2376
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2377
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2378
  bool init_mark_was_synchronous = false; // until proven otherwise
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2379
  while (_collectorState != Idling) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2380
    if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2381
      gclog_or_tty->print_cr("Thread " INTPTR_FORMAT " in CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2382
        Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2383
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2384
    switch (_collectorState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2385
      case InitialMarking:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2386
        init_mark_was_synchronous = true;  // fact to be exploited in re-mark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2387
        checkpointRootsInitial(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2388
        assert(_collectorState == Marking, "Collector state should have changed"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2389
          " within checkpointRootsInitial()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2390
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2391
      case Marking:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2392
        // initial marking in checkpointRootsInitialWork has been completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2393
        if (VerifyDuringGC &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2394
            GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2395
          gclog_or_tty->print("Verify before initial mark: ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2396
          Universe::verify(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2397
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2398
        {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2399
          bool res = markFromRoots(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2400
          assert(res && _collectorState == FinalMarking, "Collector state should "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2401
            "have changed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2402
          break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2403
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2404
      case FinalMarking:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2405
        if (VerifyDuringGC &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2406
            GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2407
          gclog_or_tty->print("Verify before re-mark: ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2408
          Universe::verify(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2409
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2410
        checkpointRootsFinal(false, clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2411
                             init_mark_was_synchronous);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2412
        assert(_collectorState == Sweeping, "Collector state should not "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2413
          "have changed within checkpointRootsFinal()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2414
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2415
      case Sweeping:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2416
        // final marking in checkpointRootsFinal has been completed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2417
        if (VerifyDuringGC &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2418
            GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2419
          gclog_or_tty->print("Verify before sweep: ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2420
          Universe::verify(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2421
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2422
        sweep(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2423
        assert(_collectorState == Resizing, "Incorrect state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2424
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2425
      case Resizing: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2426
        // Sweeping has been completed; the actual resize in this case
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2427
        // is done separately; nothing to be done in this state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2428
        _collectorState = Resetting;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2429
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2430
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2431
      case Resetting:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2432
        // The heap has been resized.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2433
        if (VerifyDuringGC &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2434
            GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2435
          gclog_or_tty->print("Verify before reset: ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2436
          Universe::verify(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2437
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2438
        reset(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2439
        assert(_collectorState == Idling, "Collector state should "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2440
          "have changed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2441
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2442
      case Precleaning:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2443
      case AbortablePreclean:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2444
        // Elide the preclean phase
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2445
        _collectorState = FinalMarking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2446
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2447
      default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2448
        ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2449
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2450
    if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2451
      gclog_or_tty->print_cr("  Thread " INTPTR_FORMAT " done - next CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2452
        Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2453
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2454
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2455
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2456
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2457
    GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2458
    size_policy()->ms_collection_end(gch->gc_cause());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2459
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2460
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2461
  if (VerifyAfterGC &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2462
      GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2463
    Universe::verify(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2464
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2465
  if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2466
    gclog_or_tty->print_cr("CMS Thread " INTPTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2467
      " exiting collection CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2468
      Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2469
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2470
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2471
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2472
bool CMSCollector::waitForForegroundGC() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2473
  bool res = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2474
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2475
         "CMS thread should have CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2476
  // Block the foreground collector until the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2477
  // background collectors decides whether to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2478
  // yield.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2479
  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2480
  _foregroundGCShouldWait = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2481
  if (_foregroundGCIsActive) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2482
    // The background collector yields to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2483
    // foreground collector and returns a value
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2484
    // indicating that it has yielded.  The foreground
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2485
    // collector can proceed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2486
    res = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2487
    _foregroundGCShouldWait = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2488
    ConcurrentMarkSweepThread::clear_CMS_flag(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2489
      ConcurrentMarkSweepThread::CMS_cms_has_token);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2490
    ConcurrentMarkSweepThread::set_CMS_flag(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2491
      ConcurrentMarkSweepThread::CMS_cms_wants_token);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2492
    // Get a possibly blocked foreground thread going
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2493
    CGC_lock->notify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2494
    if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2495
      gclog_or_tty->print_cr("CMS Thread " INTPTR_FORMAT " waiting at CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2496
        Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2497
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2498
    while (_foregroundGCIsActive) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2499
      CGC_lock->wait(Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2500
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2501
    ConcurrentMarkSweepThread::set_CMS_flag(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2502
      ConcurrentMarkSweepThread::CMS_cms_has_token);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2503
    ConcurrentMarkSweepThread::clear_CMS_flag(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2504
      ConcurrentMarkSweepThread::CMS_cms_wants_token);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2505
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2506
  if (TraceCMSState) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2507
    gclog_or_tty->print_cr("CMS Thread " INTPTR_FORMAT " continuing at CMS state %d",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2508
      Thread::current(), _collectorState);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2509
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2510
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2511
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2512
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2513
// Because of the need to lock the free lists and other structures in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2514
// the collector, common to all the generations that the collector is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2515
// collecting, we need the gc_prologues of individual CMS generations
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2516
// delegate to their collector. It may have been simpler had the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2517
// current infrastructure allowed one to call a prologue on a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2518
// collector. In the absence of that we have the generation's
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2519
// prologue delegate to the collector, which delegates back
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2520
// some "local" work to a worker method in the individual generations
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2521
// that it's responsible for collecting, while itself doing any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2522
// work common to all generations it's responsible for. A similar
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2523
// comment applies to the  gc_epilogue()'s.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2524
// The role of the varaible _between_prologue_and_epilogue is to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2525
// enforce the invocation protocol.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2526
void CMSCollector::gc_prologue(bool full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2527
  // Call gc_prologue_work() for each CMSGen and PermGen that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2528
  // we are responsible for.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2529
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2530
  // The following locking discipline assumes that we are only called
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2531
  // when the world is stopped.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2532
  assert(SafepointSynchronize::is_at_safepoint(), "world is stopped assumption");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2533
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2534
  // The CMSCollector prologue must call the gc_prologues for the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2535
  // "generations" (including PermGen if any) that it's responsible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2536
  // for.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2537
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2538
  assert(   Thread::current()->is_VM_thread()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2539
         || (   CMSScavengeBeforeRemark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2540
             && Thread::current()->is_ConcurrentGC_thread()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2541
         "Incorrect thread type for prologue execution");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2542
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2543
  if (_between_prologue_and_epilogue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2544
    // We have already been invoked; this is a gc_prologue delegation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2545
    // from yet another CMS generation that we are responsible for, just
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2546
    // ignore it since all relevant work has already been done.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2547
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2548
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2549
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2550
  // set a bit saying prologue has been called; cleared in epilogue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2551
  _between_prologue_and_epilogue = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2552
  // Claim locks for common data structures, then call gc_prologue_work()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2553
  // for each CMSGen and PermGen that we are responsible for.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2554
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2555
  getFreelistLocks();   // gets free list locks on constituent spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2556
  bitMapLock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2557
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2558
  // Should call gc_prologue_work() for all cms gens we are responsible for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2559
  bool registerClosure =    _collectorState >= Marking
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2560
                         && _collectorState < Sweeping;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2561
  ModUnionClosure* muc = ParallelGCThreads > 0 ? &_modUnionClosurePar
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2562
                                               : &_modUnionClosure;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2563
  _cmsGen->gc_prologue_work(full, registerClosure, muc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2564
  _permGen->gc_prologue_work(full, registerClosure, muc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2565
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2566
  if (!full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2567
    stats().record_gc0_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2568
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2569
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2570
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2571
void ConcurrentMarkSweepGeneration::gc_prologue(bool full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2572
  // Delegate to CMScollector which knows how to coordinate between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2573
  // this and any other CMS generations that it is responsible for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2574
  // collecting.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2575
  collector()->gc_prologue(full);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2576
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2577
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2578
// This is a "private" interface for use by this generation's CMSCollector.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2579
// Not to be called directly by any other entity (for instance,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2580
// GenCollectedHeap, which calls the "public" gc_prologue method above).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2581
void ConcurrentMarkSweepGeneration::gc_prologue_work(bool full,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2582
  bool registerClosure, ModUnionClosure* modUnionClosure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2583
  assert(!incremental_collection_failed(), "Shouldn't be set yet");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2584
  assert(cmsSpace()->preconsumptionDirtyCardClosure() == NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2585
    "Should be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2586
  if (registerClosure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2587
    cmsSpace()->setPreconsumptionDirtyCardClosure(modUnionClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2588
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2589
  cmsSpace()->gc_prologue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2590
  // Clear stat counters
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2591
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2592
    assert(_numObjectsPromoted == 0, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2593
    assert(_numWordsPromoted   == 0, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2594
    if (Verbose && PrintGC) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2595
      gclog_or_tty->print("Allocated "SIZE_FORMAT" objects, "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2596
                          SIZE_FORMAT" bytes concurrently",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2597
      _numObjectsAllocated, _numWordsAllocated*sizeof(HeapWord));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2598
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2599
    _numObjectsAllocated = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2600
    _numWordsAllocated   = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2601
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2602
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2603
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2604
void CMSCollector::gc_epilogue(bool full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2605
  // The following locking discipline assumes that we are only called
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2606
  // when the world is stopped.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2607
  assert(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2608
         "world is stopped assumption");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2609
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2610
  // Currently the CMS epilogue (see CompactibleFreeListSpace) merely checks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2611
  // if linear allocation blocks need to be appropriately marked to allow the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2612
  // the blocks to be parsable. We also check here whether we need to nudge the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2613
  // CMS collector thread to start a new cycle (if it's not already active).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2614
  assert(   Thread::current()->is_VM_thread()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2615
         || (   CMSScavengeBeforeRemark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2616
             && Thread::current()->is_ConcurrentGC_thread()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2617
         "Incorrect thread type for epilogue execution");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2618
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2619
  if (!_between_prologue_and_epilogue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2620
    // We have already been invoked; this is a gc_epilogue delegation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2621
    // from yet another CMS generation that we are responsible for, just
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2622
    // ignore it since all relevant work has already been done.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2623
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2624
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2625
  assert(haveFreelistLocks(), "must have freelist locks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2626
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2627
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2628
  _cmsGen->gc_epilogue_work(full);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2629
  _permGen->gc_epilogue_work(full);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2630
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2631
  if (_collectorState == AbortablePreclean || _collectorState == Precleaning) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2632
    // in case sampling was not already enabled, enable it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2633
    _start_sampling = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2634
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2635
  // reset _eden_chunk_array so sampling starts afresh
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2636
  _eden_chunk_index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2637
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2638
  size_t cms_used   = _cmsGen->cmsSpace()->used();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2639
  size_t perm_used  = _permGen->cmsSpace()->used();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2640
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2641
  // update performance counters - this uses a special version of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2642
  // update_counters() that allows the utilization to be passed as a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2643
  // parameter, avoiding multiple calls to used().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2644
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2645
  _cmsGen->update_counters(cms_used);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2646
  _permGen->update_counters(perm_used);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2647
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2648
  if (CMSIncrementalMode) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2649
    icms_update_allocation_limits();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2650
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2651
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2652
  bitMapLock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2653
  releaseFreelistLocks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2654
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2655
  _between_prologue_and_epilogue = false;  // ready for next cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2656
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2657
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2658
void ConcurrentMarkSweepGeneration::gc_epilogue(bool full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2659
  collector()->gc_epilogue(full);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2660
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2661
  // Also reset promotion tracking in par gc thread states.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2662
  if (ParallelGCThreads > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2663
    for (uint i = 0; i < ParallelGCThreads; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2664
      _par_gc_thread_states[i]->promo.stopTrackingPromotions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2665
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2666
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2667
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2668
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2669
void ConcurrentMarkSweepGeneration::gc_epilogue_work(bool full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2670
  assert(!incremental_collection_failed(), "Should have been cleared");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2671
  cmsSpace()->setPreconsumptionDirtyCardClosure(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2672
  cmsSpace()->gc_epilogue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2673
    // Print stat counters
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2674
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2675
    assert(_numObjectsAllocated == 0, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2676
    assert(_numWordsAllocated == 0, "check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2677
    if (Verbose && PrintGC) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2678
      gclog_or_tty->print("Promoted "SIZE_FORMAT" objects, "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2679
                          SIZE_FORMAT" bytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2680
                 _numObjectsPromoted, _numWordsPromoted*sizeof(HeapWord));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2681
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2682
    _numObjectsPromoted = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2683
    _numWordsPromoted   = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2684
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2685
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2686
  if (PrintGC && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2687
    // Call down the chain in contiguous_available needs the freelistLock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2688
    // so print this out before releasing the freeListLock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2689
    gclog_or_tty->print(" Contiguous available "SIZE_FORMAT" bytes ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2690
                        contiguous_available());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2691
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2692
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2693
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2694
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2695
bool CMSCollector::have_cms_token() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2696
  Thread* thr = Thread::current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2697
  if (thr->is_VM_thread()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2698
    return ConcurrentMarkSweepThread::vm_thread_has_cms_token();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2699
  } else if (thr->is_ConcurrentGC_thread()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2700
    return ConcurrentMarkSweepThread::cms_thread_has_cms_token();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2701
  } else if (thr->is_GC_task_thread()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2702
    return ConcurrentMarkSweepThread::vm_thread_has_cms_token() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2703
           ParGCRareEvent_lock->owned_by_self();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2704
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2705
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2706
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2707
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2708
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2709
// Check reachability of the given heap address in CMS generation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2710
// treating all other generations as roots.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2711
bool CMSCollector::is_cms_reachable(HeapWord* addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2712
  // We could "guarantee" below, rather than assert, but i'll
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2713
  // leave these as "asserts" so that an adventurous debugger
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2714
  // could try this in the product build provided some subset of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2715
  // the conditions were met, provided they were intersted in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2716
  // results and knew that the computation below wouldn't interfere
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2717
  // with other concurrent computations mutating the structures
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2718
  // being read or written.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2719
  assert(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2720
         "Else mutations in object graph will make answer suspect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2721
  assert(have_cms_token(), "Should hold cms token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2722
  assert(haveFreelistLocks(), "must hold free list locks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2723
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2724
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2725
  // Clear the marking bit map array before starting, but, just
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2726
  // for kicks, first report if the given address is already marked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2727
  gclog_or_tty->print_cr("Start: Address 0x%x is%s marked", addr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2728
                _markBitMap.isMarked(addr) ? "" : " not");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2729
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2730
  if (verify_after_remark()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2731
    MutexLockerEx x(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2732
    bool result = verification_mark_bm()->isMarked(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2733
    gclog_or_tty->print_cr("TransitiveMark: Address 0x%x %s marked", addr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2734
                           result ? "IS" : "is NOT");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2735
    return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2736
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2737
    gclog_or_tty->print_cr("Could not compute result");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2738
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2739
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2740
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2741
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2742
////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2743
// CMS Verification Support
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2744
////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2745
// Following the remark phase, the following invariant
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2746
// should hold -- each object in the CMS heap which is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2747
// marked in markBitMap() should be marked in the verification_mark_bm().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2748
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2749
class VerifyMarkedClosure: public BitMapClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2750
  CMSBitMap* _marks;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2751
  bool       _failed;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2752
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2753
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2754
  VerifyMarkedClosure(CMSBitMap* bm): _marks(bm), _failed(false) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2755
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2756
  void do_bit(size_t offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2757
    HeapWord* addr = _marks->offsetToHeapWord(offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2758
    if (!_marks->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2759
      oop(addr)->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2760
      gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2761
      _failed = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2762
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2763
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2764
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2765
  bool failed() { return _failed; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2766
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2767
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2768
bool CMSCollector::verify_after_remark() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2769
  gclog_or_tty->print(" [Verifying CMS Marking... ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2770
  MutexLockerEx ml(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2771
  static bool init = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2772
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2773
  assert(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2774
         "Else mutations in object graph will make answer suspect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2775
  assert(have_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2776
         "Else there may be mutual interference in use of "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2777
         " verification data structures");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2778
  assert(_collectorState > Marking && _collectorState <= Sweeping,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2779
         "Else marking info checked here may be obsolete");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2780
  assert(haveFreelistLocks(), "must hold free list locks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2781
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2782
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2783
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2784
  // Allocate marking bit map if not already allocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2785
  if (!init) { // first time
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2786
    if (!verification_mark_bm()->allocate(_span)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2787
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2788
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2789
    init = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2790
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2791
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2792
  assert(verification_mark_stack()->isEmpty(), "Should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2793
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2794
  // Turn off refs discovery -- so we will be tracing through refs.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2795
  // This is as intended, because by this time
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2796
  // GC must already have cleared any refs that need to be cleared,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2797
  // and traced those that need to be marked; moreover,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2798
  // the marking done here is not going to intefere in any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2799
  // way with the marking information used by GC.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2800
  NoRefDiscovery no_discovery(ref_processor());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2801
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2802
  COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2803
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2804
  // Clear any marks from a previous round
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2805
  verification_mark_bm()->clear_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2806
  assert(verification_mark_stack()->isEmpty(), "markStack should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2807
  assert(overflow_list_is_empty(), "overflow list should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2808
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2809
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2810
  gch->ensure_parsability(false);  // fill TLABs, but no need to retire them
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2811
  // Update the saved marks which may affect the root scans.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2812
  gch->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2813
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2814
  if (CMSRemarkVerifyVariant == 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2815
    // In this first variant of verification, we complete
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2816
    // all marking, then check if the new marks-verctor is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2817
    // a subset of the CMS marks-vector.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2818
    verify_after_remark_work_1();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2819
  } else if (CMSRemarkVerifyVariant == 2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2820
    // In this second variant of verification, we flag an error
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2821
    // (i.e. an object reachable in the new marks-vector not reachable
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2822
    // in the CMS marks-vector) immediately, also indicating the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2823
    // identify of an object (A) that references the unmarked object (B) --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2824
    // presumably, a mutation to A failed to be picked up by preclean/remark?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2825
    verify_after_remark_work_2();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2826
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2827
    warning("Unrecognized value %d for CMSRemarkVerifyVariant",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2828
            CMSRemarkVerifyVariant);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2829
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2830
  gclog_or_tty->print(" done] ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2831
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2832
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2833
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2834
void CMSCollector::verify_after_remark_work_1() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2835
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2836
  HandleMark  hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2837
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2838
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2839
  // Mark from roots one level into CMS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2840
  MarkRefsIntoClosure notOlder(_span, verification_mark_bm(), true /* nmethods */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2841
  gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2842
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2843
  gch->gen_process_strong_roots(_cmsGen->level(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2844
                                true,   // younger gens are roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2845
                                true,   // collecting perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2846
                                SharedHeap::ScanningOption(roots_scanning_options()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2847
                                NULL, &notOlder);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2848
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2849
  // Now mark from the roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2850
  assert(_revisitStack.isEmpty(), "Should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2851
  MarkFromRootsClosure markFromRootsClosure(this, _span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2852
    verification_mark_bm(), verification_mark_stack(), &_revisitStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2853
    false /* don't yield */, true /* verifying */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2854
  assert(_restart_addr == NULL, "Expected pre-condition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2855
  verification_mark_bm()->iterate(&markFromRootsClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2856
  while (_restart_addr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2857
    // Deal with stack overflow: by restarting at the indicated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2858
    // address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2859
    HeapWord* ra = _restart_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2860
    markFromRootsClosure.reset(ra);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2861
    _restart_addr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2862
    verification_mark_bm()->iterate(&markFromRootsClosure, ra, _span.end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2863
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2864
  assert(verification_mark_stack()->isEmpty(), "Should have been drained");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2865
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2866
  // Should reset the revisit stack above, since no class tree
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2867
  // surgery is forthcoming.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2868
  _revisitStack.reset(); // throwing away all contents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2869
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2870
  // Marking completed -- now verify that each bit marked in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2871
  // verification_mark_bm() is also marked in markBitMap(); flag all
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2872
  // errors by printing corresponding objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2873
  VerifyMarkedClosure vcl(markBitMap());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2874
  verification_mark_bm()->iterate(&vcl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2875
  if (vcl.failed()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2876
    gclog_or_tty->print("Verification failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2877
    Universe::heap()->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2878
    fatal(" ... aborting");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2879
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2880
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2881
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2882
void CMSCollector::verify_after_remark_work_2() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2883
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2884
  HandleMark  hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2885
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2886
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2887
  // Mark from roots one level into CMS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2888
  MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2889
                                     markBitMap(), true /* nmethods */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2890
  gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2891
  gch->gen_process_strong_roots(_cmsGen->level(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2892
                                true,   // younger gens are roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2893
                                true,   // collecting perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2894
                                SharedHeap::ScanningOption(roots_scanning_options()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2895
                                NULL, &notOlder);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2896
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2897
  // Now mark from the roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2898
  assert(_revisitStack.isEmpty(), "Should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2899
  MarkFromRootsVerifyClosure markFromRootsClosure(this, _span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2900
    verification_mark_bm(), markBitMap(), verification_mark_stack());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2901
  assert(_restart_addr == NULL, "Expected pre-condition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2902
  verification_mark_bm()->iterate(&markFromRootsClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2903
  while (_restart_addr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2904
    // Deal with stack overflow: by restarting at the indicated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2905
    // address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2906
    HeapWord* ra = _restart_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2907
    markFromRootsClosure.reset(ra);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2908
    _restart_addr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2909
    verification_mark_bm()->iterate(&markFromRootsClosure, ra, _span.end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2910
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2911
  assert(verification_mark_stack()->isEmpty(), "Should have been drained");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2912
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2913
  // Should reset the revisit stack above, since no class tree
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2914
  // surgery is forthcoming.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2915
  _revisitStack.reset(); // throwing away all contents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2916
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2917
  // Marking completed -- now verify that each bit marked in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2918
  // verification_mark_bm() is also marked in markBitMap(); flag all
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2919
  // errors by printing corresponding objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2920
  VerifyMarkedClosure vcl(markBitMap());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2921
  verification_mark_bm()->iterate(&vcl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2922
  assert(!vcl.failed(), "Else verification above should not have succeeded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2923
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2924
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2925
void ConcurrentMarkSweepGeneration::save_marks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2926
  // delegate to CMS space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2927
  cmsSpace()->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2928
  for (uint i = 0; i < ParallelGCThreads; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2929
    _par_gc_thread_states[i]->promo.startTrackingPromotions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2930
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2931
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2932
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2933
bool ConcurrentMarkSweepGeneration::no_allocs_since_save_marks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2934
  return cmsSpace()->no_allocs_since_save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2935
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2936
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2937
#define CMS_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix)    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2938
                                                                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2939
void ConcurrentMarkSweepGeneration::                            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2940
oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) {   \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2941
  cl->set_generation(this);                                     \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2942
  cmsSpace()->oop_since_save_marks_iterate##nv_suffix(cl);      \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2943
  cl->reset_generation();                                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2944
  save_marks();                                                 \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2945
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2946
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2947
ALL_SINCE_SAVE_MARKS_CLOSURES(CMS_SINCE_SAVE_MARKS_DEFN)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2948
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2949
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2950
ConcurrentMarkSweepGeneration::object_iterate_since_last_GC(ObjectClosure* blk)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2951
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2952
  // Not currently implemented; need to do the following. -- ysr.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2953
  // dld -- I think that is used for some sort of allocation profiler.  So it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2954
  // really means the objects allocated by the mutator since the last
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2955
  // GC.  We could potentially implement this cheaply by recording only
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2956
  // the direct allocations in a side data structure.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2957
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2958
  // I think we probably ought not to be required to support these
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2959
  // iterations at any arbitrary point; I think there ought to be some
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2960
  // call to enable/disable allocation profiling in a generation/space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2961
  // and the iterator ought to return the objects allocated in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2962
  // gen/space since the enable call, or the last iterator call (which
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2963
  // will probably be at a GC.)  That way, for gens like CM&S that would
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2964
  // require some extra data structure to support this, we only pay the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2965
  // cost when it's in use...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2966
  cmsSpace()->object_iterate_since_last_GC(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2967
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2968
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2969
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2970
ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2971
  cl->set_generation(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2972
  younger_refs_in_space_iterate(_cmsSpace, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2973
  cl->reset_generation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2974
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2975
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2976
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2977
ConcurrentMarkSweepGeneration::oop_iterate(MemRegion mr, OopClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2978
  if (freelistLock()->owned_by_self()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2979
    Generation::oop_iterate(mr, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2980
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2981
    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2982
    Generation::oop_iterate(mr, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2983
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2984
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2985
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2986
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2987
ConcurrentMarkSweepGeneration::oop_iterate(OopClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2988
  if (freelistLock()->owned_by_self()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2989
    Generation::oop_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2990
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2991
    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2992
    Generation::oop_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2993
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2994
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2995
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2996
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2997
ConcurrentMarkSweepGeneration::object_iterate(ObjectClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2998
  if (freelistLock()->owned_by_self()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2999
    Generation::object_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3000
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3001
    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3002
    Generation::object_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3003
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3004
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3005
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3006
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3007
ConcurrentMarkSweepGeneration::pre_adjust_pointers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3008
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3009
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3010
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3011
ConcurrentMarkSweepGeneration::post_compact() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3012
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3013
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3014
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3015
ConcurrentMarkSweepGeneration::prepare_for_verify() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3016
  // Fix the linear allocation blocks to look like free blocks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3017
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3018
  // Locks are normally acquired/released in gc_prologue/gc_epilogue, but those
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3019
  // are not called when the heap is verified during universe initialization and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3020
  // at vm shutdown.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3021
  if (freelistLock()->owned_by_self()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3022
    cmsSpace()->prepare_for_verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3023
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3024
    MutexLockerEx fll(freelistLock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3025
    cmsSpace()->prepare_for_verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3026
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3027
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3028
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3029
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3030
ConcurrentMarkSweepGeneration::verify(bool allow_dirty /* ignored */) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3031
  // Locks are normally acquired/released in gc_prologue/gc_epilogue, but those
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3032
  // are not called when the heap is verified during universe initialization and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3033
  // at vm shutdown.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3034
  if (freelistLock()->owned_by_self()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3035
    cmsSpace()->verify(false /* ignored */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3036
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3037
    MutexLockerEx fll(freelistLock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3038
    cmsSpace()->verify(false /* ignored */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3039
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3040
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3041
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3042
void CMSCollector::verify(bool allow_dirty /* ignored */) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3043
  _cmsGen->verify(allow_dirty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3044
  _permGen->verify(allow_dirty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3045
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3046
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3047
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3048
bool CMSCollector::overflow_list_is_empty() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3049
  assert(_num_par_pushes >= 0, "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3050
  if (_overflow_list == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3051
    assert(_num_par_pushes == 0, "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3052
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3053
  return _overflow_list == NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3054
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3055
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3056
// The methods verify_work_stacks_empty() and verify_overflow_empty()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3057
// merely consolidate assertion checks that appear to occur together frequently.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3058
void CMSCollector::verify_work_stacks_empty() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3059
  assert(_markStack.isEmpty(), "Marking stack should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3060
  assert(overflow_list_is_empty(), "Overflow list should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3061
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3062
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3063
void CMSCollector::verify_overflow_empty() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3064
  assert(overflow_list_is_empty(), "Overflow list should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3065
  assert(no_preserved_marks(), "No preserved marks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3066
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3067
#endif // PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3068
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3069
// Decide if we want to enable class unloading as part of the
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3070
// ensuing concurrent GC cycle. We will collect the perm gen and
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3071
// unload classes if it's the case that:
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3072
// (1) an explicit gc request has been made and the flag
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3073
//     ExplicitGCInvokesConcurrentAndUnloadsClasses is set, OR
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3074
// (2) (a) class unloading is enabled at the command line, and
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3075
//     (b) (i)   perm gen threshold has been crossed, or
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3076
//         (ii)  old gen is getting really full, or
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3077
//         (iii) the previous N CMS collections did not collect the
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3078
//               perm gen
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3079
// NOTE: Provided there is no change in the state of the heap between
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3080
// calls to this method, it should have idempotent results. Moreover,
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3081
// its results should be monotonically increasing (i.e. going from 0 to 1,
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3082
// but not 1 to 0) between successive calls between which the heap was
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3083
// not collected. For the implementation below, it must thus rely on
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3084
// the property that concurrent_cycles_since_last_unload()
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3085
// will not decrease unless a collection cycle happened and that
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3086
// _permGen->should_concurrent_collect() and _cmsGen->is_too_full() are
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3087
// themselves also monotonic in that sense. See check_monotonicity()
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3088
// below.
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3089
bool CMSCollector::update_should_unload_classes() {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3090
  _should_unload_classes = false;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3091
  // Condition 1 above
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3092
  if (_full_gc_requested && ExplicitGCInvokesConcurrentAndUnloadsClasses) {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3093
    _should_unload_classes = true;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3094
  } else if (CMSClassUnloadingEnabled) { // Condition 2.a above
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3095
    // Disjuncts 2.b.(i,ii,iii) above
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3096
    _should_unload_classes = (concurrent_cycles_since_last_unload() >=
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3097
                              CMSClassUnloadingMaxInterval)
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3098
                           || _permGen->should_concurrent_collect()
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3099
                           || _cmsGen->is_too_full();
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3100
  }
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3101
  return _should_unload_classes;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3102
}
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3103
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3104
bool ConcurrentMarkSweepGeneration::is_too_full() const {
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3105
  bool res = should_concurrent_collect();
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3106
  res = res && (occupancy() > (double)CMSIsTooFullPercentage/100.0);
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3107
  return res;
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3108
}
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3109
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3110
void CMSCollector::setup_cms_unloading_and_verification_state() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3111
  const  bool should_verify =    VerifyBeforeGC || VerifyAfterGC || VerifyDuringGC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3112
                             || VerifyBeforeExit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3113
  const  int  rso           =    SharedHeap::SO_Symbols | SharedHeap::SO_Strings
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3114
                             |   SharedHeap::SO_CodeCache;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3115
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3116
  if (should_unload_classes()) {   // Should unload classes this cycle
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3117
    remove_root_scanning_option(rso);  // Shrink the root set appropriately
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3118
    set_verifying(should_verify);    // Set verification state for this cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3119
    return;                            // Nothing else needs to be done at this time
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3120
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3121
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3122
  // Not unloading classes this cycle
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3123
  assert(!should_unload_classes(), "Inconsitency!");
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  3124
  if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3125
    // We were not verifying, or we _were_ unloading classes in the last cycle,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3126
    // AND some verification options are enabled this cycle; in this case,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3127
    // we must make sure that the deadness map is allocated if not already so,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3128
    // and cleared (if already allocated previously --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3129
    // CMSBitMap::sizeInBits() is used to determine if it's allocated).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3130
    if (perm_gen_verify_bit_map()->sizeInBits() == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3131
      if (!perm_gen_verify_bit_map()->allocate(_permGen->reserved())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3132
        warning("Failed to allocate permanent generation verification CMS Bit Map;\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3133
                "permanent generation verification disabled");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3134
        return;  // Note that we leave verification disabled, so we'll retry this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3135
                 // allocation next cycle. We _could_ remember this failure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3136
                 // and skip further attempts and permanently disable verification
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3137
                 // attempts if that is considered more desirable.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3138
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3139
      assert(perm_gen_verify_bit_map()->covers(_permGen->reserved()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3140
              "_perm_gen_ver_bit_map inconsistency?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3141
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3142
      perm_gen_verify_bit_map()->clear_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3143
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3144
    // Include symbols, strings and code cache elements to prevent their resurrection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3145
    add_root_scanning_option(rso);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3146
    set_verifying(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3147
  } else if (verifying() && !should_verify) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3148
    // We were verifying, but some verification flags got disabled.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3149
    set_verifying(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3150
    // Exclude symbols, strings and code cache elements from root scanning to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3151
    // reduce IM and RM pauses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3152
    remove_root_scanning_option(rso);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3153
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3154
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3155
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3156
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3157
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3158
HeapWord* CMSCollector::block_start(const void* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3159
  const HeapWord* addr = (HeapWord*)p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3160
  if (_span.contains(p)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3161
    if (_cmsGen->cmsSpace()->is_in_reserved(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3162
      return _cmsGen->cmsSpace()->block_start(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3163
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3164
      assert(_permGen->cmsSpace()->is_in_reserved(addr),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3165
             "Inconsistent _span?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3166
      return _permGen->cmsSpace()->block_start(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3167
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3168
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3169
  return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3170
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3171
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3172
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3173
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3174
ConcurrentMarkSweepGeneration::expand_and_allocate(size_t word_size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3175
                                                   bool   tlab,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3176
                                                   bool   parallel) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3177
  assert(!tlab, "Can't deal with TLAB allocation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3178
  MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3179
  expand(word_size*HeapWordSize, MinHeapDeltaBytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3180
    CMSExpansionCause::_satisfy_allocation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3181
  if (GCExpandToAllocateDelayMillis > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3182
    os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3183
  }
182
eae79d9b9d46 6642634: Test nsk/regression/b6186200 crashed with SIGSEGV
ysr
parents: 180
diff changeset
  3184
  return have_lock_and_allocate(word_size, tlab);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3185
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3186
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3187
// YSR: All of this generation expansion/shrinking stuff is an exact copy of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3188
// OneContigSpaceCardGeneration, which makes me wonder if we should move this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3189
// to CardGeneration and share it...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3190
void ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3191
  CMSExpansionCause::Cause cause)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3192
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3193
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3194
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3195
  size_t aligned_bytes  = ReservedSpace::page_align_size_up(bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3196
  size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3197
  bool success = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3198
  if (aligned_expand_bytes > aligned_bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3199
    success = grow_by(aligned_expand_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3200
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3201
  if (!success) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3202
    success = grow_by(aligned_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3203
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3204
  if (!success) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3205
    size_t remaining_bytes = _virtual_space.uncommitted_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3206
    if (remaining_bytes > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3207
      success = grow_by(remaining_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3208
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3209
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3210
  if (GC_locker::is_active()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3211
    if (PrintGC && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3212
      gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3213
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3214
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3215
  // remember why we expanded; this information is used
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3216
  // by shouldConcurrentCollect() when making decisions on whether to start
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3217
  // a new CMS cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3218
  if (success) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3219
    set_expansion_cause(cause);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3220
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3221
      gclog_or_tty->print_cr("Expanded CMS gen for %s",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3222
        CMSExpansionCause::to_string(cause));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3223
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3224
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3225
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3226
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3227
HeapWord* ConcurrentMarkSweepGeneration::expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3228
  HeapWord* res = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3229
  MutexLocker x(ParGCRareEvent_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3230
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3231
    // Expansion by some other thread might make alloc OK now:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3232
    res = ps->lab.alloc(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3233
    if (res != NULL) return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3234
    // If there's not enough expansion space available, give up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3235
    if (_virtual_space.uncommitted_size() < (word_sz * HeapWordSize)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3236
      return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3237
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3238
    // Otherwise, we try expansion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3239
    expand(word_sz*HeapWordSize, MinHeapDeltaBytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3240
      CMSExpansionCause::_allocate_par_lab);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3241
    // Now go around the loop and try alloc again;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3242
    // A competing par_promote might beat us to the expansion space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3243
    // so we may go around the loop again if promotion fails agaion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3244
    if (GCExpandToAllocateDelayMillis > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3245
      os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3246
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3247
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3248
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3249
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3250
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3251
bool ConcurrentMarkSweepGeneration::expand_and_ensure_spooling_space(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3252
  PromotionInfo* promo) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3253
  MutexLocker x(ParGCRareEvent_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3254
  size_t refill_size_bytes = promo->refillSize() * HeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3255
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3256
    // Expansion by some other thread might make alloc OK now:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3257
    if (promo->ensure_spooling_space()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3258
      assert(promo->has_spooling_space(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3259
             "Post-condition of successful ensure_spooling_space()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3260
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3261
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3262
    // If there's not enough expansion space available, give up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3263
    if (_virtual_space.uncommitted_size() < refill_size_bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3264
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3265
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3266
    // Otherwise, we try expansion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3267
    expand(refill_size_bytes, MinHeapDeltaBytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3268
      CMSExpansionCause::_allocate_par_spooling_space);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3269
    // Now go around the loop and try alloc again;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3270
    // A competing allocation might beat us to the expansion space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3271
    // so we may go around the loop again if allocation fails again.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3272
    if (GCExpandToAllocateDelayMillis > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3273
      os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3274
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3275
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3276
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3277
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3278
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3279
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3280
void ConcurrentMarkSweepGeneration::shrink(size_t bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3281
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3282
  size_t size = ReservedSpace::page_align_size_down(bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3283
  if (size > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3284
    shrink_by(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3285
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3286
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3287
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3288
bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3289
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3290
  bool result = _virtual_space.expand_by(bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3291
  if (result) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3292
    HeapWord* old_end = _cmsSpace->end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3293
    size_t new_word_size =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3294
      heap_word_size(_virtual_space.committed_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3295
    MemRegion mr(_cmsSpace->bottom(), new_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3296
    _bts->resize(new_word_size);  // resize the block offset shared array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3297
    Universe::heap()->barrier_set()->resize_covered_region(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3298
    // Hmmmm... why doesn't CFLS::set_end verify locking?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3299
    // This is quite ugly; FIX ME XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3300
    _cmsSpace->assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3301
    _cmsSpace->set_end((HeapWord*)_virtual_space.high());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3302
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3303
    // update the space and generation capacity counters
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3304
    if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3305
      _space_counters->update_capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3306
      _gen_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3307
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3308
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3309
    if (Verbose && PrintGC) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3310
      size_t new_mem_size = _virtual_space.committed_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3311
      size_t old_mem_size = new_mem_size - bytes;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3312
      gclog_or_tty->print_cr("Expanding %s from %ldK by %ldK to %ldK",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3313
                    name(), old_mem_size/K, bytes/K, new_mem_size/K);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3314
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3315
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3316
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3317
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3318
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3319
bool ConcurrentMarkSweepGeneration::grow_to_reserved() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3320
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3321
  bool success = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3322
  const size_t remaining_bytes = _virtual_space.uncommitted_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3323
  if (remaining_bytes > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3324
    success = grow_by(remaining_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3325
    DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3326
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3327
  return success;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3328
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3329
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3330
void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3331
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3332
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3333
  // XXX Fix when compaction is implemented.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3334
  warning("Shrinking of CMS not yet implemented");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3335
  return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3336
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3337
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3338
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3339
// Simple ctor/dtor wrapper for accounting & timer chores around concurrent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3340
// phases.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3341
class CMSPhaseAccounting: public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3342
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3343
  CMSPhaseAccounting(CMSCollector *collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3344
                     const char *phase,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3345
                     bool print_cr = true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3346
  ~CMSPhaseAccounting();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3347
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3348
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3349
  CMSCollector *_collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3350
  const char *_phase;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3351
  elapsedTimer _wallclock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3352
  bool _print_cr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3353
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3354
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3355
  // Not MT-safe; so do not pass around these StackObj's
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3356
  // where they may be accessed by other threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3357
  jlong wallclock_millis() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3358
    assert(_wallclock.is_active(), "Wall clock should not stop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3359
    _wallclock.stop();  // to record time
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3360
    jlong ret = _wallclock.milliseconds();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3361
    _wallclock.start(); // restart
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3362
    return ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3363
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3364
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3365
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3366
CMSPhaseAccounting::CMSPhaseAccounting(CMSCollector *collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3367
                                       const char *phase,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3368
                                       bool print_cr) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3369
  _collector(collector), _phase(phase), _print_cr(print_cr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3370
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3371
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3372
    _collector->resetYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3373
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3374
  if (PrintGCDetails && PrintGCTimeStamps) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3375
    gclog_or_tty->date_stamp(PrintGCDateStamps);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3376
    gclog_or_tty->stamp();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3377
    gclog_or_tty->print_cr(": [%s-concurrent-%s-start]",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3378
      _collector->cmsGen()->short_name(), _phase);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3379
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3380
  _collector->resetTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3381
  _wallclock.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3382
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3383
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3384
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3385
CMSPhaseAccounting::~CMSPhaseAccounting() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3386
  assert(_wallclock.is_active(), "Wall clock should not have stopped");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3387
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3388
  _wallclock.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3389
  if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3390
    gclog_or_tty->date_stamp(PrintGCDateStamps);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3391
    if (PrintGCTimeStamps) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3392
      gclog_or_tty->stamp();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3393
      gclog_or_tty->print(": ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3394
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3395
    gclog_or_tty->print("[%s-concurrent-%s: %3.3f/%3.3f secs]",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3396
                 _collector->cmsGen()->short_name(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3397
                 _phase, _collector->timerValue(), _wallclock.seconds());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3398
    if (_print_cr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3399
      gclog_or_tty->print_cr("");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3400
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3401
    if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3402
      gclog_or_tty->print_cr(" (CMS-concurrent-%s yielded %d times)", _phase,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3403
                    _collector->yields());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3404
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3405
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3406
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3407
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3408
// CMS work
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3409
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3410
// Checkpoint the roots into this generation from outside
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3411
// this generation. [Note this initial checkpoint need only
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3412
// be approximate -- we'll do a catch up phase subsequently.]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3413
void CMSCollector::checkpointRootsInitial(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3414
  assert(_collectorState == InitialMarking, "Wrong collector state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3415
  check_correct_thread_executing();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3416
  ReferenceProcessor* rp = ref_processor();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3417
  SpecializationStats::clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3418
  assert(_restart_addr == NULL, "Control point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3419
  if (asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3420
    // acquire locks for subsequent manipulations
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3421
    MutexLockerEx x(bitMapLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3422
                    Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3423
    checkpointRootsInitialWork(asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3424
    rp->verify_no_references_recorded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3425
    rp->enable_discovery(); // enable ("weak") refs discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3426
    _collectorState = Marking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3427
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3428
    // (Weak) Refs discovery: this is controlled from genCollectedHeap::do_collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3429
    // which recognizes if we are a CMS generation, and doesn't try to turn on
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3430
    // discovery; verify that they aren't meddling.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3431
    assert(!rp->discovery_is_atomic(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3432
           "incorrect setting of discovery predicate");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3433
    assert(!rp->discovery_enabled(), "genCollectedHeap shouldn't control "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3434
           "ref discovery for this generation kind");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3435
    // already have locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3436
    checkpointRootsInitialWork(asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3437
    rp->enable_discovery(); // now enable ("weak") refs discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3438
    _collectorState = Marking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3439
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3440
  SpecializationStats::print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3441
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3442
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3443
void CMSCollector::checkpointRootsInitialWork(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3444
  assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3445
  assert(_collectorState == InitialMarking, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3446
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3447
  // If there has not been a GC[n-1] since last GC[n] cycle completed,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3448
  // precede our marking with a collection of all
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3449
  // younger generations to keep floating garbage to a minimum.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3450
  // XXX: we won't do this for now -- it's an optimization to be done later.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3451
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3452
  // already have locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3453
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3454
  assert(_markBitMap.isAllClear(), "was reset at end of previous cycle");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3455
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3456
  // Setup the verification and class unloading state for this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3457
  // CMS collection cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3458
  setup_cms_unloading_and_verification_state();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3459
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3460
  NOT_PRODUCT(TraceTime t("\ncheckpointRootsInitialWork",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3461
    PrintGCDetails && Verbose, true, gclog_or_tty);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3462
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3463
    size_policy()->checkpoint_roots_initial_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3464
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3465
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3466
  // Reset all the PLAB chunk arrays if necessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3467
  if (_survivor_plab_array != NULL && !CMSPLABRecordAlways) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3468
    reset_survivor_plab_arrays();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3469
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3470
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3471
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3472
  HandleMark  hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3473
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3474
  FalseClosure falseClosure;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3475
  // In the case of a synchronous collection, we will elide the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3476
  // remark step, so it's important to catch all the nmethod oops
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3477
  // in this step; hence the last argument to the constrcutor below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3478
  MarkRefsIntoClosure notOlder(_span, &_markBitMap, !asynch /* nmethods */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3479
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3480
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3481
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3482
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3483
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3484
  gch->ensure_parsability(false);  // fill TLABs, but no need to retire them
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3485
  // Update the saved marks which may affect the root scans.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3486
  gch->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3487
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3488
  // weak reference processing has not started yet.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3489
  ref_processor()->set_enqueuing_is_done(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3490
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3491
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3492
    COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3493
    gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3494
    gch->gen_process_strong_roots(_cmsGen->level(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3495
                                  true,   // younger gens are roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3496
                                  true,   // collecting perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3497
                                  SharedHeap::ScanningOption(roots_scanning_options()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3498
                                  NULL, &notOlder);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3499
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3500
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3501
  // Clear mod-union table; it will be dirtied in the prologue of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3502
  // CMS generation per each younger generation collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3503
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3504
  assert(_modUnionTable.isAllClear(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3505
       "Was cleared in most recent final checkpoint phase"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3506
       " or no bits are set in the gc_prologue before the start of the next "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3507
       "subsequent marking phase.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3508
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3509
  // Temporarily disabled, since pre/post-consumption closures don't
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3510
  // care about precleaned cards
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3511
  #if 0
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3512
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3513
    MemRegion mr = MemRegion((HeapWord*)_virtual_space.low(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3514
                             (HeapWord*)_virtual_space.high());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3515
    _ct->ct_bs()->preclean_dirty_cards(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3516
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3517
  #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3518
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3519
  // Save the end of the used_region of the constituent generations
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3520
  // to be used to limit the extent of sweep in each generation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3521
  save_sweep_limits();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3522
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3523
    size_policy()->checkpoint_roots_initial_end(gch->gc_cause());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3524
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3525
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3526
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3527
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3528
bool CMSCollector::markFromRoots(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3529
  // we might be tempted to assert that:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3530
  // assert(asynch == !SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3531
  //        "inconsistent argument?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3532
  // However that wouldn't be right, because it's possible that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3533
  // a safepoint is indeed in progress as a younger generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3534
  // stop-the-world GC happens even as we mark in this generation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3535
  assert(_collectorState == Marking, "inconsistent state?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3536
  check_correct_thread_executing();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3537
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3538
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3539
  bool res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3540
  if (asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3541
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3542
    // Start the timers for adaptive size policy for the concurrent phases
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3543
    // Do it here so that the foreground MS can use the concurrent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3544
    // timer since a foreground MS might has the sweep done concurrently
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3545
    // or STW.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3546
    if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3547
      size_policy()->concurrent_marking_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3548
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3549
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3550
    // Weak ref discovery note: We may be discovering weak
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3551
    // refs in this generation concurrent (but interleaved) with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3552
    // weak ref discovery by a younger generation collector.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3553
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3554
    CMSTokenSyncWithLocks ts(true, bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3555
    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3556
    CMSPhaseAccounting pa(this, "mark", !PrintGCDetails);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3557
    res = markFromRootsWork(asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3558
    if (res) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3559
      _collectorState = Precleaning;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3560
    } else { // We failed and a foreground collection wants to take over
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3561
      assert(_foregroundGCIsActive, "internal state inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3562
      assert(_restart_addr == NULL,  "foreground will restart from scratch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3563
      if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3564
        gclog_or_tty->print_cr("bailing out to foreground collection");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3565
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3566
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3567
    if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3568
      size_policy()->concurrent_marking_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3569
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3570
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3571
    assert(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3572
           "inconsistent with asynch == false");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3573
    if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3574
      size_policy()->ms_collection_marking_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3575
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3576
    // already have locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3577
    res = markFromRootsWork(asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3578
    _collectorState = FinalMarking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3579
    if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3580
      GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3581
      size_policy()->ms_collection_marking_end(gch->gc_cause());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3582
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3583
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3584
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3585
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3586
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3587
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3588
bool CMSCollector::markFromRootsWork(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3589
  // iterate over marked bits in bit map, doing a full scan and mark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3590
  // from these roots using the following algorithm:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3591
  // . if oop is to the right of the current scan pointer,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3592
  //   mark corresponding bit (we'll process it later)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3593
  // . else (oop is to left of current scan pointer)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3594
  //   push oop on marking stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3595
  // . drain the marking stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3596
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3597
  // Note that when we do a marking step we need to hold the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3598
  // bit map lock -- recall that direct allocation (by mutators)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3599
  // and promotion (by younger generation collectors) is also
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3600
  // marking the bit map. [the so-called allocate live policy.]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3601
  // Because the implementation of bit map marking is not
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3602
  // robust wrt simultaneous marking of bits in the same word,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3603
  // we need to make sure that there is no such interference
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3604
  // between concurrent such updates.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3605
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3606
  // already have locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3607
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3608
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3609
  // Clear the revisit stack, just in case there are any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3610
  // obsolete contents from a short-circuited previous CMS cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3611
  _revisitStack.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3612
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3613
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3614
  assert(_revisitStack.isEmpty(), "tabula rasa");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3615
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3616
  bool result = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3617
  if (CMSConcurrentMTEnabled && ParallelCMSThreads > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3618
    result = do_marking_mt(asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3619
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3620
    result = do_marking_st(asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3621
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3622
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3623
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3624
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3625
// Forward decl
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3626
class CMSConcMarkingTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3627
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3628
class CMSConcMarkingTerminator: public ParallelTaskTerminator {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3629
  CMSCollector*       _collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3630
  CMSConcMarkingTask* _task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3631
  bool _yield;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3632
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3633
  virtual void yield();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3634
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3635
  // "n_threads" is the number of threads to be terminated.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3636
  // "queue_set" is a set of work queues of other threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3637
  // "collector" is the CMS collector associated with this task terminator.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3638
  // "yield" indicates whether we need the gang as a whole to yield.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3639
  CMSConcMarkingTerminator(int n_threads, TaskQueueSetSuper* queue_set,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3640
                           CMSCollector* collector, bool yield) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3641
    ParallelTaskTerminator(n_threads, queue_set),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3642
    _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3643
    _yield(yield) { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3644
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3645
  void set_task(CMSConcMarkingTask* task) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3646
    _task = task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3647
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3648
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3649
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3650
// MT Concurrent Marking Task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3651
class CMSConcMarkingTask: public YieldingFlexibleGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3652
  CMSCollector* _collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3653
  YieldingFlexibleWorkGang* _workers;        // the whole gang
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3654
  int           _n_workers;                  // requested/desired # workers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3655
  bool          _asynch;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3656
  bool          _result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3657
  CompactibleFreeListSpace*  _cms_space;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3658
  CompactibleFreeListSpace* _perm_space;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3659
  HeapWord*     _global_finger;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3660
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3661
  //  Exposed here for yielding support
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3662
  Mutex* const _bit_map_lock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3663
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3664
  // The per thread work queues, available here for stealing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3665
  OopTaskQueueSet*  _task_queues;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3666
  CMSConcMarkingTerminator _term;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3667
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3668
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3669
  CMSConcMarkingTask(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3670
                 CompactibleFreeListSpace* cms_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3671
                 CompactibleFreeListSpace* perm_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3672
                 bool asynch, int n_workers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3673
                 YieldingFlexibleWorkGang* workers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3674
                 OopTaskQueueSet* task_queues):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3675
    YieldingFlexibleGangTask("Concurrent marking done multi-threaded"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3676
    _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3677
    _cms_space(cms_space),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3678
    _perm_space(perm_space),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3679
    _asynch(asynch), _n_workers(n_workers), _result(true),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3680
    _workers(workers), _task_queues(task_queues),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3681
    _term(n_workers, task_queues, _collector, asynch),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3682
    _bit_map_lock(collector->bitMapLock())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3683
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3684
    assert(n_workers <= workers->total_workers(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3685
           "Else termination won't work correctly today"); // XXX FIX ME!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3686
    _requested_size = n_workers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3687
    _term.set_task(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3688
    assert(_cms_space->bottom() < _perm_space->bottom(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3689
           "Finger incorrectly initialized below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3690
    _global_finger = _cms_space->bottom();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3691
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3692
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3693
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3694
  OopTaskQueueSet* task_queues()  { return _task_queues; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3695
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3696
  OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3697
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3698
  HeapWord** global_finger_addr() { return &_global_finger; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3699
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3700
  CMSConcMarkingTerminator* terminator() { return &_term; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3701
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3702
  void work(int i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3703
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3704
  virtual void coordinator_yield();  // stuff done by coordinator
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3705
  bool result() { return _result; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3706
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3707
  void reset(HeapWord* ra) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3708
    _term.reset_for_reuse();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3709
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3710
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3711
  static bool get_work_from_overflow_stack(CMSMarkStack* ovflw_stk,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3712
                                           OopTaskQueue* work_q);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3713
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3714
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3715
  void do_scan_and_mark(int i, CompactibleFreeListSpace* sp);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3716
  void do_work_steal(int i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3717
  void bump_global_finger(HeapWord* f);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3718
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3719
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3720
void CMSConcMarkingTerminator::yield() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3721
  if (ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3722
      !_collector->foregroundGCIsActive() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3723
      _yield) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3724
    _task->yield();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3725
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3726
    ParallelTaskTerminator::yield();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3727
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3728
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3729
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3730
////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3731
// Concurrent Marking Algorithm Sketch
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3732
////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3733
// Until all tasks exhausted (both spaces):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3734
// -- claim next available chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3735
// -- bump global finger via CAS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3736
// -- find first object that starts in this chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3737
//    and start scanning bitmap from that position
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3738
// -- scan marked objects for oops
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3739
// -- CAS-mark target, and if successful:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3740
//    . if target oop is above global finger (volatile read)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3741
//      nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3742
//    . if target oop is in chunk and above local finger
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3743
//        then nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3744
//    . else push on work-queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3745
// -- Deal with possible overflow issues:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3746
//    . local work-queue overflow causes stuff to be pushed on
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3747
//      global (common) overflow queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3748
//    . always first empty local work queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3749
//    . then get a batch of oops from global work queue if any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3750
//    . then do work stealing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3751
// -- When all tasks claimed (both spaces)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3752
//    and local work queue empty,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3753
//    then in a loop do:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3754
//    . check global overflow stack; steal a batch of oops and trace
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3755
//    . try to steal from other threads oif GOS is empty
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3756
//    . if neither is available, offer termination
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3757
// -- Terminate and return result
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3758
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3759
void CMSConcMarkingTask::work(int i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3760
  elapsedTimer _timer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3761
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3762
  HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3763
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3764
  DEBUG_ONLY(_collector->verify_overflow_empty();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3765
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3766
  // Before we begin work, our work queue should be empty
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3767
  assert(work_queue(i)->size() == 0, "Expected to be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3768
  // Scan the bitmap covering _cms_space, tracing through grey objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3769
  _timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3770
  do_scan_and_mark(i, _cms_space);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3771
  _timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3772
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3773
    gclog_or_tty->print_cr("Finished cms space scanning in %dth thread: %3.3f sec",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3774
      i, _timer.seconds()); // XXX: need xxx/xxx type of notation, two timers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3775
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3776
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3777
  // ... do the same for the _perm_space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3778
  _timer.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3779
  _timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3780
  do_scan_and_mark(i, _perm_space);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3781
  _timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3782
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3783
    gclog_or_tty->print_cr("Finished perm space scanning in %dth thread: %3.3f sec",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3784
      i, _timer.seconds()); // XXX: need xxx/xxx type of notation, two timers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3785
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3786
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3787
  // ... do work stealing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3788
  _timer.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3789
  _timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3790
  do_work_steal(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3791
  _timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3792
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3793
    gclog_or_tty->print_cr("Finished work stealing in %dth thread: %3.3f sec",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3794
      i, _timer.seconds()); // XXX: need xxx/xxx type of notation, two timers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3795
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3796
  assert(_collector->_markStack.isEmpty(), "Should have been emptied");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3797
  assert(work_queue(i)->size() == 0, "Should have been emptied");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3798
  // Note that under the current task protocol, the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3799
  // following assertion is true even of the spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3800
  // expanded since the completion of the concurrent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3801
  // marking. XXX This will likely change under a strict
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3802
  // ABORT semantics.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3803
  assert(_global_finger >  _cms_space->end() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3804
         _global_finger >= _perm_space->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3805
         "All tasks have been completed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3806
  DEBUG_ONLY(_collector->verify_overflow_empty();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3807
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3808
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3809
void CMSConcMarkingTask::bump_global_finger(HeapWord* f) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3810
  HeapWord* read = _global_finger;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3811
  HeapWord* cur  = read;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3812
  while (f > read) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3813
    cur = read;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3814
    read = (HeapWord*) Atomic::cmpxchg_ptr(f, &_global_finger, cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3815
    if (cur == read) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3816
      // our cas succeeded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3817
      assert(_global_finger >= f, "protocol consistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3818
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3819
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3820
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3821
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3822
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3823
// This is really inefficient, and should be redone by
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3824
// using (not yet available) block-read and -write interfaces to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3825
// stack and the work_queue. XXX FIX ME !!!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3826
bool CMSConcMarkingTask::get_work_from_overflow_stack(CMSMarkStack* ovflw_stk,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3827
                                                      OopTaskQueue* work_q) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3828
  // Fast lock-free check
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3829
  if (ovflw_stk->length() == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3830
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3831
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3832
  assert(work_q->size() == 0, "Shouldn't steal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3833
  MutexLockerEx ml(ovflw_stk->par_lock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3834
                   Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3835
  // Grab up to 1/4 the size of the work queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3836
  size_t num = MIN2((size_t)work_q->max_elems()/4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3837
                    (size_t)ParGCDesiredObjsFromOverflowList);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3838
  num = MIN2(num, ovflw_stk->length());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3839
  for (int i = (int) num; i > 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3840
    oop cur = ovflw_stk->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3841
    assert(cur != NULL, "Counted wrong?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3842
    work_q->push(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3843
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3844
  return num > 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3845
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3846
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3847
void CMSConcMarkingTask::do_scan_and_mark(int i, CompactibleFreeListSpace* sp) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3848
  SequentialSubTasksDone* pst = sp->conc_par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3849
  int n_tasks = pst->n_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3850
  // We allow that there may be no tasks to do here because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3851
  // we are restarting after a stack overflow.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3852
  assert(pst->valid() || n_tasks == 0, "Uninitializd use?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3853
  int nth_task = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3854
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3855
  HeapWord* start = sp->bottom();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3856
  size_t chunk_size = sp->marking_task_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3857
  while (!pst->is_task_claimed(/* reference */ nth_task)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3858
    // Having claimed the nth task in this space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3859
    // compute the chunk that it corresponds to:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3860
    MemRegion span = MemRegion(start + nth_task*chunk_size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3861
                               start + (nth_task+1)*chunk_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3862
    // Try and bump the global finger via a CAS;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3863
    // note that we need to do the global finger bump
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3864
    // _before_ taking the intersection below, because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3865
    // the task corresponding to that region will be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3866
    // deemed done even if the used_region() expands
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3867
    // because of allocation -- as it almost certainly will
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3868
    // during start-up while the threads yield in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3869
    // closure below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3870
    HeapWord* finger = span.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3871
    bump_global_finger(finger);   // atomically
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3872
    // There are null tasks here corresponding to chunks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3873
    // beyond the "top" address of the space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3874
    span = span.intersection(sp->used_region());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3875
    if (!span.is_empty()) {  // Non-null task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3876
      // We want to skip the first object because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3877
      // the protocol is to scan any object in its entirety
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3878
      // that _starts_ in this span; a fortiori, any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3879
      // object starting in an earlier span is scanned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3880
      // as part of an earlier claimed task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3881
      // Below we use the "careful" version of block_start
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3882
      // so we do not try to navigate uninitialized objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3883
      HeapWord* prev_obj = sp->block_start_careful(span.start());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3884
      // Below we use a variant of block_size that uses the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3885
      // Printezis bits to avoid waiting for allocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3886
      // objects to become initialized/parsable.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3887
      while (prev_obj < span.start()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3888
        size_t sz = sp->block_size_no_stall(prev_obj, _collector);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3889
        if (sz > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3890
          prev_obj += sz;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3891
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3892
          // In this case we may end up doing a bit of redundant
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3893
          // scanning, but that appears unavoidable, short of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3894
          // locking the free list locks; see bug 6324141.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3895
          break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3896
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3897
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3898
      if (prev_obj < span.end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3899
        MemRegion my_span = MemRegion(prev_obj, span.end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3900
        // Do the marking work within a non-empty span --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3901
        // the last argument to the constructor indicates whether the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3902
        // iteration should be incremental with periodic yields.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3903
        Par_MarkFromRootsClosure cl(this, _collector, my_span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3904
                                    &_collector->_markBitMap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3905
                                    work_queue(i),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3906
                                    &_collector->_markStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3907
                                    &_collector->_revisitStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3908
                                    _asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3909
        _collector->_markBitMap.iterate(&cl, my_span.start(), my_span.end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3910
      } // else nothing to do for this task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3911
    }   // else nothing to do for this task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3912
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3913
  // We'd be tempted to assert here that since there are no
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3914
  // more tasks left to claim in this space, the global_finger
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3915
  // must exceed space->top() and a fortiori space->end(). However,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3916
  // that would not quite be correct because the bumping of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3917
  // global_finger occurs strictly after the claiming of a task,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3918
  // so by the time we reach here the global finger may not yet
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3919
  // have been bumped up by the thread that claimed the last
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3920
  // task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3921
  pst->all_tasks_completed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3922
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3923
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3924
class Par_ConcMarkingClosure: public OopClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3925
  CMSCollector* _collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3926
  MemRegion     _span;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3927
  CMSBitMap*    _bit_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3928
  CMSMarkStack* _overflow_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3929
  CMSMarkStack* _revisit_stack;     // XXXXXX Check proper use
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3930
  OopTaskQueue* _work_queue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3931
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3932
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3933
  Par_ConcMarkingClosure(CMSCollector* collector, OopTaskQueue* work_queue,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3934
                         CMSBitMap* bit_map, CMSMarkStack* overflow_stack):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3935
    _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3936
    _span(_collector->_span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3937
    _work_queue(work_queue),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3938
    _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3939
    _overflow_stack(overflow_stack) { }   // need to initialize revisit stack etc.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3940
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3941
  void do_oop(oop* p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3942
  void trim_queue(size_t max);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3943
  void handle_stack_overflow(HeapWord* lost);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3944
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3945
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3946
// Grey object rescan during work stealing phase --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3947
// the salient assumption here is that stolen oops must
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3948
// always be initialized, so we do not need to check for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3949
// uninitialized objects before scanning here.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3950
void Par_ConcMarkingClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3951
  oop    this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3952
  assert(this_oop->is_oop_or_null(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3953
         "expected an oop or NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3954
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3955
  // Check if oop points into the CMS generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3956
  // and is not marked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3957
  if (_span.contains(addr) && !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3958
    // a white object ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3959
    // If we manage to "claim" the object, by being the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3960
    // first thread to mark it, then we push it on our
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3961
    // marking stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3962
    if (_bit_map->par_mark(addr)) {     // ... now grey
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3963
      // push on work queue (grey set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3964
      bool simulate_overflow = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3965
      NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3966
        if (CMSMarkStackOverflowALot &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3967
            _collector->simulate_overflow()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3968
          // simulate a stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3969
          simulate_overflow = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3970
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3971
      )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3972
      if (simulate_overflow ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3973
          !(_work_queue->push(this_oop) || _overflow_stack->par_push(this_oop))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3974
        // stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3975
        if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3976
          gclog_or_tty->print_cr("CMS marking stack overflow (benign) at "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3977
                                 SIZE_FORMAT, _overflow_stack->capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3978
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3979
        // We cannot assert that the overflow stack is full because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3980
        // it may have been emptied since.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3981
        assert(simulate_overflow ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3982
               _work_queue->size() == _work_queue->max_elems(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3983
              "Else push should have succeeded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3984
        handle_stack_overflow(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3985
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3986
    } // Else, some other thread got there first
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3987
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3988
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3989
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3990
void Par_ConcMarkingClosure::trim_queue(size_t max) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3991
  while (_work_queue->size() > max) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3992
    oop new_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3993
    if (_work_queue->pop_local(new_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3994
      assert(new_oop->is_oop(), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3995
      assert(_bit_map->isMarked((HeapWord*)new_oop), "Grey object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3996
      assert(_span.contains((HeapWord*)new_oop), "Not in span");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3997
      assert(new_oop->is_parsable(), "Should be parsable");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3998
      new_oop->oop_iterate(this);  // do_oop() above
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3999
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4000
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4001
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4002
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4003
// Upon stack overflow, we discard (part of) the stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4004
// remembering the least address amongst those discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4005
// in CMSCollector's _restart_address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4006
void Par_ConcMarkingClosure::handle_stack_overflow(HeapWord* lost) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4007
  // We need to do this under a mutex to prevent other
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4008
  // workers from interfering with the expansion below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4009
  MutexLockerEx ml(_overflow_stack->par_lock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4010
                   Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4011
  // Remember the least grey address discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4012
  HeapWord* ra = (HeapWord*)_overflow_stack->least_value(lost);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4013
  _collector->lower_restart_addr(ra);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4014
  _overflow_stack->reset();  // discard stack contents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4015
  _overflow_stack->expand(); // expand the stack if possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4016
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4017
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4018
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4019
void CMSConcMarkingTask::do_work_steal(int i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4020
  OopTaskQueue* work_q = work_queue(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4021
  oop obj_to_scan;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4022
  CMSBitMap* bm = &(_collector->_markBitMap);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4023
  CMSMarkStack* ovflw = &(_collector->_markStack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4024
  int* seed = _collector->hash_seed(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4025
  Par_ConcMarkingClosure cl(_collector, work_q, bm, ovflw);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4026
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4027
    cl.trim_queue(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4028
    assert(work_q->size() == 0, "Should have been emptied above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4029
    if (get_work_from_overflow_stack(ovflw, work_q)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4030
      // Can't assert below because the work obtained from the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4031
      // overflow stack may already have been stolen from us.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4032
      // assert(work_q->size() > 0, "Work from overflow stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4033
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4034
    } else if (task_queues()->steal(i, seed, /* reference */ obj_to_scan)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4035
      assert(obj_to_scan->is_oop(), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4036
      assert(bm->isMarked((HeapWord*)obj_to_scan), "Grey object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4037
      obj_to_scan->oop_iterate(&cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4038
    } else if (terminator()->offer_termination()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4039
      assert(work_q->size() == 0, "Impossible!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4040
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4041
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4042
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4043
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4044
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4045
// This is run by the CMS (coordinator) thread.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4046
void CMSConcMarkingTask::coordinator_yield() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4047
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4048
         "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4049
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4050
  // First give up the locks, then yield, then re-lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4051
  // We should probably use a constructor/destructor idiom to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4052
  // do this unlock/lock or modify the MutexUnlocker class to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4053
  // serve our purpose. XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4054
  assert_lock_strong(_bit_map_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4055
  _bit_map_lock->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4056
  ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4057
  ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4058
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4059
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4060
    _collector->incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4061
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4062
  _collector->icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4063
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4064
  // It is possible for whichever thread initiated the yield request
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4065
  // not to get a chance to wake up and take the bitmap lock between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4066
  // this thread releasing it and reacquiring it. So, while the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4067
  // should_yield() flag is on, let's sleep for a bit to give the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4068
  // other thread a chance to wake up. The limit imposed on the number
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4069
  // of iterations is defensive, to avoid any unforseen circumstances
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4070
  // putting us into an infinite loop. Since it's always been this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4071
  // (coordinator_yield()) method that was observed to cause the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4072
  // problem, we are using a parameter (CMSCoordinatorYieldSleepCount)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4073
  // which is by default non-zero. For the other seven methods that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4074
  // also perform the yield operation, as are using a different
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4075
  // parameter (CMSYieldSleepCount) which is by default zero. This way we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4076
  // can enable the sleeping for those methods too, if necessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4077
  // See 6442774.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4078
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4079
  // We really need to reconsider the synchronization between the GC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4080
  // thread and the yield-requesting threads in the future and we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4081
  // should really use wait/notify, which is the recommended
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4082
  // way of doing this type of interaction. Additionally, we should
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4083
  // consolidate the eight methods that do the yield operation and they
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4084
  // are almost identical into one for better maintenability and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4085
  // readability. See 6445193.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4086
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4087
  // Tony 2006.06.29
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4088
  for (unsigned i = 0; i < CMSCoordinatorYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4089
                       ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4090
                       !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4091
    os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4092
    ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4093
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4094
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4095
  ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4096
  _bit_map_lock->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4097
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4098
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4099
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4100
bool CMSCollector::do_marking_mt(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4101
  assert(ParallelCMSThreads > 0 && conc_workers() != NULL, "precondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4102
  // In the future this would be determined ergonomically, based
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4103
  // on #cpu's, # active mutator threads (and load), and mutation rate.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4104
  int num_workers = ParallelCMSThreads;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4105
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4106
  CompactibleFreeListSpace* cms_space  = _cmsGen->cmsSpace();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4107
  CompactibleFreeListSpace* perm_space = _permGen->cmsSpace();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4108
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4109
  CMSConcMarkingTask tsk(this, cms_space, perm_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4110
                         asynch, num_workers /* number requested XXX */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4111
                         conc_workers(), task_queues());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4112
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4113
  // Since the actual number of workers we get may be different
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4114
  // from the number we requested above, do we need to do anything different
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4115
  // below? In particular, may be we need to subclass the SequantialSubTasksDone
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4116
  // class?? XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4117
  cms_space ->initialize_sequential_subtasks_for_marking(num_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4118
  perm_space->initialize_sequential_subtasks_for_marking(num_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4119
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4120
  // Refs discovery is already non-atomic.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4121
  assert(!ref_processor()->discovery_is_atomic(), "Should be non-atomic");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4122
  // Mutate the Refs discovery so it is MT during the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4123
  // multi-threaded marking phase.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4124
  ReferenceProcessorMTMutator mt(ref_processor(), num_workers > 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4125
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4126
  conc_workers()->start_task(&tsk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4127
  while (tsk.yielded()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4128
    tsk.coordinator_yield();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4129
    conc_workers()->continue_task(&tsk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4130
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4131
  // If the task was aborted, _restart_addr will be non-NULL
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4132
  assert(tsk.completed() || _restart_addr != NULL, "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4133
  while (_restart_addr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4134
    // XXX For now we do not make use of ABORTED state and have not
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4135
    // yet implemented the right abort semantics (even in the original
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4136
    // single-threaded CMS case). That needs some more investigation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4137
    // and is deferred for now; see CR# TBF. 07252005YSR. XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4138
    assert(!CMSAbortSemantics || tsk.aborted(), "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4139
    // If _restart_addr is non-NULL, a marking stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4140
    // occured; we need to do a fresh marking iteration from the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4141
    // indicated restart address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4142
    if (_foregroundGCIsActive && asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4143
      // We may be running into repeated stack overflows, having
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4144
      // reached the limit of the stack size, while making very
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4145
      // slow forward progress. It may be best to bail out and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4146
      // let the foreground collector do its job.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4147
      // Clear _restart_addr, so that foreground GC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4148
      // works from scratch. This avoids the headache of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4149
      // a "rescan" which would otherwise be needed because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4150
      // of the dirty mod union table & card table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4151
      _restart_addr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4152
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4153
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4154
    // Adjust the task to restart from _restart_addr
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4155
    tsk.reset(_restart_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4156
    cms_space ->initialize_sequential_subtasks_for_marking(num_workers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4157
                  _restart_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4158
    perm_space->initialize_sequential_subtasks_for_marking(num_workers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4159
                  _restart_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4160
    _restart_addr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4161
    // Get the workers going again
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4162
    conc_workers()->start_task(&tsk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4163
    while (tsk.yielded()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4164
      tsk.coordinator_yield();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4165
      conc_workers()->continue_task(&tsk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4166
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4167
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4168
  assert(tsk.completed(), "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4169
  assert(tsk.result() == true, "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4170
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4171
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4172
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4173
bool CMSCollector::do_marking_st(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4174
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4175
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4176
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4177
  MarkFromRootsClosure markFromRootsClosure(this, _span, &_markBitMap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4178
    &_markStack, &_revisitStack, CMSYield && asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4179
  // the last argument to iterate indicates whether the iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4180
  // should be incremental with periodic yields.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4181
  _markBitMap.iterate(&markFromRootsClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4182
  // If _restart_addr is non-NULL, a marking stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4183
  // occured; we need to do a fresh iteration from the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4184
  // indicated restart address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4185
  while (_restart_addr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4186
    if (_foregroundGCIsActive && asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4187
      // We may be running into repeated stack overflows, having
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4188
      // reached the limit of the stack size, while making very
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4189
      // slow forward progress. It may be best to bail out and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4190
      // let the foreground collector do its job.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4191
      // Clear _restart_addr, so that foreground GC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4192
      // works from scratch. This avoids the headache of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4193
      // a "rescan" which would otherwise be needed because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4194
      // of the dirty mod union table & card table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4195
      _restart_addr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4196
      return false;  // indicating failure to complete marking
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4197
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4198
    // Deal with stack overflow:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4199
    // we restart marking from _restart_addr
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4200
    HeapWord* ra = _restart_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4201
    markFromRootsClosure.reset(ra);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4202
    _restart_addr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4203
    _markBitMap.iterate(&markFromRootsClosure, ra, _span.end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4204
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4205
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4206
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4207
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4208
void CMSCollector::preclean() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4209
  check_correct_thread_executing();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4210
  assert(Thread::current()->is_ConcurrentGC_thread(), "Wrong thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4211
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4212
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4213
  _abort_preclean = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4214
  if (CMSPrecleaningEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4215
    _eden_chunk_index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4216
    size_t used = get_eden_used();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4217
    size_t capacity = get_eden_capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4218
    // Don't start sampling unless we will get sufficiently
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4219
    // many samples.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4220
    if (used < (capacity/(CMSScheduleRemarkSamplingRatio * 100)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4221
                * CMSScheduleRemarkEdenPenetration)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4222
      _start_sampling = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4223
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4224
      _start_sampling = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4225
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4226
    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4227
    CMSPhaseAccounting pa(this, "preclean", !PrintGCDetails);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4228
    preclean_work(CMSPrecleanRefLists1, CMSPrecleanSurvivors1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4229
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4230
  CMSTokenSync x(true); // is cms thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4231
  if (CMSPrecleaningEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4232
    sample_eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4233
    _collectorState = AbortablePreclean;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4234
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4235
    _collectorState = FinalMarking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4236
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4237
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4238
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4239
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4240
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4241
// Try and schedule the remark such that young gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4242
// occupancy is CMSScheduleRemarkEdenPenetration %.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4243
void CMSCollector::abortable_preclean() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4244
  check_correct_thread_executing();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4245
  assert(CMSPrecleaningEnabled,  "Inconsistent control state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4246
  assert(_collectorState == AbortablePreclean, "Inconsistent control state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4247
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4248
  // If Eden's current occupancy is below this threshold,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4249
  // immediately schedule the remark; else preclean
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4250
  // past the next scavenge in an effort to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4251
  // schedule the pause as described avove. By choosing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4252
  // CMSScheduleRemarkEdenSizeThreshold >= max eden size
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4253
  // we will never do an actual abortable preclean cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4254
  if (get_eden_used() > CMSScheduleRemarkEdenSizeThreshold) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4255
    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4256
    CMSPhaseAccounting pa(this, "abortable-preclean", !PrintGCDetails);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4257
    // We need more smarts in the abortable preclean
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4258
    // loop below to deal with cases where allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4259
    // in young gen is very very slow, and our precleaning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4260
    // is running a losing race against a horde of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4261
    // mutators intent on flooding us with CMS updates
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4262
    // (dirty cards).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4263
    // One, admittedly dumb, strategy is to give up
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4264
    // after a certain number of abortable precleaning loops
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4265
    // or after a certain maximum time. We want to make
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4266
    // this smarter in the next iteration.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4267
    // XXX FIX ME!!! YSR
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4268
    size_t loops = 0, workdone = 0, cumworkdone = 0, waited = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4269
    while (!(should_abort_preclean() ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4270
             ConcurrentMarkSweepThread::should_terminate())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4271
      workdone = preclean_work(CMSPrecleanRefLists2, CMSPrecleanSurvivors2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4272
      cumworkdone += workdone;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4273
      loops++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4274
      // Voluntarily terminate abortable preclean phase if we have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4275
      // been at it for too long.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4276
      if ((CMSMaxAbortablePrecleanLoops != 0) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4277
          loops >= CMSMaxAbortablePrecleanLoops) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4278
        if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4279
          gclog_or_tty->print(" CMS: abort preclean due to loops ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4280
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4281
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4282
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4283
      if (pa.wallclock_millis() > CMSMaxAbortablePrecleanTime) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4284
        if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4285
          gclog_or_tty->print(" CMS: abort preclean due to time ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4286
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4287
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4288
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4289
      // If we are doing little work each iteration, we should
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4290
      // take a short break.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4291
      if (workdone < CMSAbortablePrecleanMinWorkPerIteration) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4292
        // Sleep for some time, waiting for work to accumulate
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4293
        stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4294
        cmsThread()->wait_on_cms_lock(CMSAbortablePrecleanWaitMillis);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4295
        startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4296
        waited++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4297
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4298
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4299
    if (PrintCMSStatistics > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4300
      gclog_or_tty->print(" [%d iterations, %d waits, %d cards)] ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4301
                          loops, waited, cumworkdone);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4302
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4303
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4304
  CMSTokenSync x(true); // is cms thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4305
  if (_collectorState != Idling) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4306
    assert(_collectorState == AbortablePreclean,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4307
           "Spontaneous state transition?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4308
    _collectorState = FinalMarking;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4309
  } // Else, a foreground collection completed this CMS cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4310
  return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4311
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4312
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4313
// Respond to an Eden sampling opportunity
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4314
void CMSCollector::sample_eden() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4315
  // Make sure a young gc cannot sneak in between our
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4316
  // reading and recording of a sample.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4317
  assert(Thread::current()->is_ConcurrentGC_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4318
         "Only the cms thread may collect Eden samples");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4319
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4320
         "Should collect samples while holding CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4321
  if (!_start_sampling) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4322
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4323
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4324
  if (_eden_chunk_array) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4325
    if (_eden_chunk_index < _eden_chunk_capacity) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4326
      _eden_chunk_array[_eden_chunk_index] = *_top_addr;   // take sample
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4327
      assert(_eden_chunk_array[_eden_chunk_index] <= *_end_addr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4328
             "Unexpected state of Eden");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4329
      // We'd like to check that what we just sampled is an oop-start address;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4330
      // however, we cannot do that here since the object may not yet have been
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4331
      // initialized. So we'll instead do the check when we _use_ this sample
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4332
      // later.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4333
      if (_eden_chunk_index == 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4334
          (pointer_delta(_eden_chunk_array[_eden_chunk_index],
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4335
                         _eden_chunk_array[_eden_chunk_index-1])
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4336
           >= CMSSamplingGrain)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4337
        _eden_chunk_index++;  // commit sample
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4338
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4339
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4340
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4341
  if ((_collectorState == AbortablePreclean) && !_abort_preclean) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4342
    size_t used = get_eden_used();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4343
    size_t capacity = get_eden_capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4344
    assert(used <= capacity, "Unexpected state of Eden");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4345
    if (used >  (capacity/100 * CMSScheduleRemarkEdenPenetration)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4346
      _abort_preclean = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4347
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4348
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4349
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4350
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4351
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4352
size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4353
  assert(_collectorState == Precleaning ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4354
         _collectorState == AbortablePreclean, "incorrect state");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4355
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4356
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4357
  // Do one pass of scrubbing the discovered reference lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4358
  // to remove any reference objects with strongly-reachable
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4359
  // referents.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4360
  if (clean_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4361
    ReferenceProcessor* rp = ref_processor();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4362
    CMSPrecleanRefsYieldClosure yield_cl(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4363
    assert(rp->span().equals(_span), "Spans should be equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4364
    CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4365
                                   &_markStack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4366
    CMSDrainMarkingStackClosure complete_trace(this,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4367
                                  _span, &_markBitMap, &_markStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4368
                                  &keep_alive);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4369
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4370
    // We don't want this step to interfere with a young
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4371
    // collection because we don't want to take CPU
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4372
    // or memory bandwidth away from the young GC threads
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4373
    // (which may be as many as there are CPUs).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4374
    // Note that we don't need to protect ourselves from
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4375
    // interference with mutators because they can't
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4376
    // manipulate the discovered reference lists nor affect
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4377
    // the computed reachability of the referents, the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4378
    // only properties manipulated by the precleaning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4379
    // of these reference lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4380
    stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4381
    CMSTokenSyncWithLocks x(true /* is cms thread */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4382
                            bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4383
    startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4384
    sample_eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4385
    // The following will yield to allow foreground
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4386
    // collection to proceed promptly. XXX YSR:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4387
    // The code in this method may need further
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4388
    // tweaking for better performance and some restructuring
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4389
    // for cleaner interfaces.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4390
    rp->preclean_discovered_references(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4391
          rp->is_alive_non_header(), &keep_alive, &complete_trace,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4392
          &yield_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4393
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4394
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4395
  if (clean_survivor) {  // preclean the active survivor space(s)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4396
    assert(_young_gen->kind() == Generation::DefNew ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4397
           _young_gen->kind() == Generation::ParNew ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4398
           _young_gen->kind() == Generation::ASParNew,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4399
         "incorrect type for cast");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4400
    DefNewGeneration* dng = (DefNewGeneration*)_young_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4401
    PushAndMarkClosure pam_cl(this, _span, ref_processor(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4402
                             &_markBitMap, &_modUnionTable,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4403
                             &_markStack, &_revisitStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4404
                             true /* precleaning phase */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4405
    stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4406
    CMSTokenSyncWithLocks ts(true /* is cms thread */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4407
                             bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4408
    startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4409
    unsigned int before_count =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4410
      GenCollectedHeap::heap()->total_collections();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4411
    SurvivorSpacePrecleanClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4412
      sss_cl(this, _span, &_markBitMap, &_markStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4413
             &pam_cl, before_count, CMSYield);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4414
    dng->from()->object_iterate_careful(&sss_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4415
    dng->to()->object_iterate_careful(&sss_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4416
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4417
  MarkRefsIntoAndScanClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4418
    mrias_cl(_span, ref_processor(), &_markBitMap, &_modUnionTable,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4419
             &_markStack, &_revisitStack, this, CMSYield,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4420
             true /* precleaning phase */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4421
  // CAUTION: The following closure has persistent state that may need to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4422
  // be reset upon a decrease in the sequence of addresses it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4423
  // processes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4424
  ScanMarkedObjectsAgainCarefullyClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4425
    smoac_cl(this, _span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4426
      &_markBitMap, &_markStack, &_revisitStack, &mrias_cl, CMSYield);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4427
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4428
  // Preclean dirty cards in ModUnionTable and CardTable using
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4429
  // appropriate convergence criterion;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4430
  // repeat CMSPrecleanIter times unless we find that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4431
  // we are losing.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4432
  assert(CMSPrecleanIter < 10, "CMSPrecleanIter is too large");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4433
  assert(CMSPrecleanNumerator < CMSPrecleanDenominator,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4434
         "Bad convergence multiplier");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4435
  assert(CMSPrecleanThreshold >= 100,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4436
         "Unreasonably low CMSPrecleanThreshold");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4437
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4438
  size_t numIter, cumNumCards, lastNumCards, curNumCards;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4439
  for (numIter = 0, cumNumCards = lastNumCards = curNumCards = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4440
       numIter < CMSPrecleanIter;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4441
       numIter++, lastNumCards = curNumCards, cumNumCards += curNumCards) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4442
    curNumCards  = preclean_mod_union_table(_cmsGen, &smoac_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4443
    if (CMSPermGenPrecleaningEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4444
      curNumCards  += preclean_mod_union_table(_permGen, &smoac_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4445
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4446
    if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4447
      gclog_or_tty->print(" (modUnionTable: %d cards)", curNumCards);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4448
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4449
    // Either there are very few dirty cards, so re-mark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4450
    // pause will be small anyway, or our pre-cleaning isn't
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4451
    // that much faster than the rate at which cards are being
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4452
    // dirtied, so we might as well stop and re-mark since
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4453
    // precleaning won't improve our re-mark time by much.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4454
    if (curNumCards <= CMSPrecleanThreshold ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4455
        (numIter > 0 &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4456
         (curNumCards * CMSPrecleanDenominator >
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4457
         lastNumCards * CMSPrecleanNumerator))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4458
      numIter++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4459
      cumNumCards += curNumCards;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4460
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4461
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4462
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4463
  curNumCards = preclean_card_table(_cmsGen, &smoac_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4464
  if (CMSPermGenPrecleaningEnabled) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4465
    curNumCards += preclean_card_table(_permGen, &smoac_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4466
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4467
  cumNumCards += curNumCards;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4468
  if (PrintGCDetails && PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4469
    gclog_or_tty->print_cr(" (cardTable: %d cards, re-scanned %d cards, %d iterations)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4470
                  curNumCards, cumNumCards, numIter);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4471
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4472
  return cumNumCards;   // as a measure of useful work done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4473
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4474
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4475
// PRECLEANING NOTES:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4476
// Precleaning involves:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4477
// . reading the bits of the modUnionTable and clearing the set bits.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4478
// . For the cards corresponding to the set bits, we scan the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4479
//   objects on those cards. This means we need the free_list_lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4480
//   so that we can safely iterate over the CMS space when scanning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4481
//   for oops.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4482
// . When we scan the objects, we'll be both reading and setting
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4483
//   marks in the marking bit map, so we'll need the marking bit map.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4484
// . For protecting _collector_state transitions, we take the CGC_lock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4485
//   Note that any races in the reading of of card table entries by the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4486
//   CMS thread on the one hand and the clearing of those entries by the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4487
//   VM thread or the setting of those entries by the mutator threads on the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4488
//   other are quite benign. However, for efficiency it makes sense to keep
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4489
//   the VM thread from racing with the CMS thread while the latter is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4490
//   dirty card info to the modUnionTable. We therefore also use the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4491
//   CGC_lock to protect the reading of the card table and the mod union
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4492
//   table by the CM thread.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4493
// . We run concurrently with mutator updates, so scanning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4494
//   needs to be done carefully  -- we should not try to scan
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4495
//   potentially uninitialized objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4496
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4497
// Locking strategy: While holding the CGC_lock, we scan over and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4498
// reset a maximal dirty range of the mod union / card tables, then lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4499
// the free_list_lock and bitmap lock to do a full marking, then
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4500
// release these locks; and repeat the cycle. This allows for a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4501
// certain amount of fairness in the sharing of these locks between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4502
// the CMS collector on the one hand, and the VM thread and the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4503
// mutators on the other.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4504
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4505
// NOTE: preclean_mod_union_table() and preclean_card_table()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4506
// further below are largely identical; if you need to modify
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4507
// one of these methods, please check the other method too.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4508
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4509
size_t CMSCollector::preclean_mod_union_table(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4510
  ConcurrentMarkSweepGeneration* gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4511
  ScanMarkedObjectsAgainCarefullyClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4512
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4513
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4514
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4515
  // strategy: starting with the first card, accumulate contiguous
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4516
  // ranges of dirty cards; clear these cards, then scan the region
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4517
  // covered by these cards.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4518
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4519
  // Since all of the MUT is committed ahead, we can just use
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4520
  // that, in case the generations expand while we are precleaning.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4521
  // It might also be fine to just use the committed part of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4522
  // generation, but we might potentially miss cards when the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4523
  // generation is rapidly expanding while we are in the midst
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4524
  // of precleaning.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4525
  HeapWord* startAddr = gen->reserved().start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4526
  HeapWord* endAddr   = gen->reserved().end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4527
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4528
  cl->setFreelistLock(gen->freelistLock());   // needed for yielding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4529
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4530
  size_t numDirtyCards, cumNumDirtyCards;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4531
  HeapWord *nextAddr, *lastAddr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4532
  for (cumNumDirtyCards = numDirtyCards = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4533
       nextAddr = lastAddr = startAddr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4534
       nextAddr < endAddr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4535
       nextAddr = lastAddr, cumNumDirtyCards += numDirtyCards) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4536
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4537
    ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4538
    HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4539
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4540
    MemRegion dirtyRegion;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4541
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4542
      stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4543
      CMSTokenSync ts(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4544
      startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4545
      sample_eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4546
      // Get dirty region starting at nextOffset (inclusive),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4547
      // simultaneously clearing it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4548
      dirtyRegion =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4549
        _modUnionTable.getAndClearMarkedRegion(nextAddr, endAddr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4550
      assert(dirtyRegion.start() >= nextAddr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4551
             "returned region inconsistent?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4552
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4553
    // Remember where the next search should begin.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4554
    // The returned region (if non-empty) is a right open interval,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4555
    // so lastOffset is obtained from the right end of that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4556
    // interval.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4557
    lastAddr = dirtyRegion.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4558
    // Should do something more transparent and less hacky XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4559
    numDirtyCards =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4560
      _modUnionTable.heapWordDiffToOffsetDiff(dirtyRegion.word_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4561
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4562
    // We'll scan the cards in the dirty region (with periodic
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4563
    // yields for foreground GC as needed).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4564
    if (!dirtyRegion.is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4565
      assert(numDirtyCards > 0, "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4566
      HeapWord* stop_point = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4567
      {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4568
        stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4569
        CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4570
                                 bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4571
        startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4572
        verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4573
        verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4574
        sample_eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4575
        stop_point =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4576
          gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4577
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4578
      if (stop_point != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4579
        // The careful iteration stopped early either because it found an
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4580
        // uninitialized object, or because we were in the midst of an
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4581
        // "abortable preclean", which should now be aborted. Redirty
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4582
        // the bits corresponding to the partially-scanned or unscanned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4583
        // cards. We'll either restart at the next block boundary or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4584
        // abort the preclean.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4585
        assert((CMSPermGenPrecleaningEnabled && (gen == _permGen)) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4586
               (_collectorState == AbortablePreclean && should_abort_preclean()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4587
               "Unparsable objects should only be in perm gen.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4588
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4589
        stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4590
        CMSTokenSyncWithLocks ts(true, bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4591
        startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4592
        _modUnionTable.mark_range(MemRegion(stop_point, dirtyRegion.end()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4593
        if (should_abort_preclean()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4594
          break; // out of preclean loop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4595
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4596
          // Compute the next address at which preclean should pick up;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4597
          // might need bitMapLock in order to read P-bits.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4598
          lastAddr = next_card_start_after_block(stop_point);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4599
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4600
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4601
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4602
      assert(lastAddr == endAddr, "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4603
      assert(numDirtyCards == 0, "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4604
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4605
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4606
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4607
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4608
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4609
  return cumNumDirtyCards;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4610
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4611
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4612
// NOTE: preclean_mod_union_table() above and preclean_card_table()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4613
// below are largely identical; if you need to modify
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4614
// one of these methods, please check the other method too.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4615
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4616
size_t CMSCollector::preclean_card_table(ConcurrentMarkSweepGeneration* gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4617
  ScanMarkedObjectsAgainCarefullyClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4618
  // strategy: it's similar to precleamModUnionTable above, in that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4619
  // we accumulate contiguous ranges of dirty cards, mark these cards
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4620
  // precleaned, then scan the region covered by these cards.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4621
  HeapWord* endAddr   = (HeapWord*)(gen->_virtual_space.high());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4622
  HeapWord* startAddr = (HeapWord*)(gen->_virtual_space.low());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4623
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4624
  cl->setFreelistLock(gen->freelistLock());   // needed for yielding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4625
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4626
  size_t numDirtyCards, cumNumDirtyCards;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4627
  HeapWord *lastAddr, *nextAddr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4628
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4629
  for (cumNumDirtyCards = numDirtyCards = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4630
       nextAddr = lastAddr = startAddr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4631
       nextAddr < endAddr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4632
       nextAddr = lastAddr, cumNumDirtyCards += numDirtyCards) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4633
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4634
    ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4635
    HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4636
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4637
    MemRegion dirtyRegion;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4638
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4639
      // See comments in "Precleaning notes" above on why we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4640
      // do this locking. XXX Could the locking overheads be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4641
      // too high when dirty cards are sparse? [I don't think so.]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4642
      stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4643
      CMSTokenSync x(true); // is cms thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4644
      startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4645
      sample_eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4646
      // Get and clear dirty region from card table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4647
      dirtyRegion = _ct->ct_bs()->dirty_card_range_after_preclean(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4648
                                    MemRegion(nextAddr, endAddr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4649
      assert(dirtyRegion.start() >= nextAddr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4650
             "returned region inconsistent?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4651
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4652
    lastAddr = dirtyRegion.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4653
    numDirtyCards =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4654
      dirtyRegion.word_size()/CardTableModRefBS::card_size_in_words;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4655
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4656
    if (!dirtyRegion.is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4657
      stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4658
      CMSTokenSyncWithLocks ts(true, gen->freelistLock(), bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4659
      startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4660
      sample_eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4661
      verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4662
      verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4663
      HeapWord* stop_point =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4664
        gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4665
      if (stop_point != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4666
        // The careful iteration stopped early because it found an
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4667
        // uninitialized object.  Redirty the bits corresponding to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4668
        // partially-scanned or unscanned cards, and start again at the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4669
        // next block boundary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4670
        assert(CMSPermGenPrecleaningEnabled ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4671
               (_collectorState == AbortablePreclean && should_abort_preclean()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4672
               "Unparsable objects should only be in perm gen.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4673
        _ct->ct_bs()->invalidate(MemRegion(stop_point, dirtyRegion.end()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4674
        if (should_abort_preclean()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4675
          break; // out of preclean loop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4676
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4677
          // Compute the next address at which preclean should pick up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4678
          lastAddr = next_card_start_after_block(stop_point);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4679
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4680
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4681
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4682
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4683
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4684
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4685
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4686
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4687
  return cumNumDirtyCards;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4688
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4689
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4690
void CMSCollector::checkpointRootsFinal(bool asynch,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4691
  bool clear_all_soft_refs, bool init_mark_was_synchronous) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4692
  assert(_collectorState == FinalMarking, "incorrect state transition?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4693
  check_correct_thread_executing();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4694
  // world is stopped at this checkpoint
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4695
  assert(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4696
         "world should be stopped");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4697
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4698
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4699
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4700
  SpecializationStats::clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4701
  if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4702
    gclog_or_tty->print("[YG occupancy: "SIZE_FORMAT" K ("SIZE_FORMAT" K)]",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4703
                        _young_gen->used() / K,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4704
                        _young_gen->capacity() / K);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4705
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4706
  if (asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4707
    if (CMSScavengeBeforeRemark) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4708
      GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4709
      // Temporarily set flag to false, GCH->do_collection will
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4710
      // expect it to be false and set to true
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4711
      FlagSetting fl(gch->_is_gc_active, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4712
      NOT_PRODUCT(TraceTime t("Scavenge-Before-Remark",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4713
        PrintGCDetails && Verbose, true, gclog_or_tty);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4714
      int level = _cmsGen->level() - 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4715
      if (level >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4716
        gch->do_collection(true,        // full (i.e. force, see below)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4717
                           false,       // !clear_all_soft_refs
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4718
                           0,           // size
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4719
                           false,       // is_tlab
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4720
                           level        // max_level
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4721
                          );
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4722
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4723
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4724
    FreelistLocker x(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4725
    MutexLockerEx y(bitMapLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4726
                    Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4727
    assert(!init_mark_was_synchronous, "but that's impossible!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4728
    checkpointRootsFinalWork(asynch, clear_all_soft_refs, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4729
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4730
    // already have all the locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4731
    checkpointRootsFinalWork(asynch, clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4732
                             init_mark_was_synchronous);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4733
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4734
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4735
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4736
  SpecializationStats::print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4737
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4738
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4739
void CMSCollector::checkpointRootsFinalWork(bool asynch,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4740
  bool clear_all_soft_refs, bool init_mark_was_synchronous) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4741
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4742
  NOT_PRODUCT(TraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, gclog_or_tty);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4743
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4744
  assert(haveFreelistLocks(), "must have free list locks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4745
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4746
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4747
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4748
    size_policy()->checkpoint_roots_final_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4749
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4750
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4751
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4752
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4753
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4754
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4755
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  4756
  if (should_unload_classes()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4757
    CodeCache::gc_prologue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4758
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4759
  assert(haveFreelistLocks(), "must have free list locks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4760
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4761
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4762
  if (!init_mark_was_synchronous) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4763
    // We might assume that we need not fill TLAB's when
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4764
    // CMSScavengeBeforeRemark is set, because we may have just done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4765
    // a scavenge which would have filled all TLAB's -- and besides
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4766
    // Eden would be empty. This however may not always be the case --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4767
    // for instance although we asked for a scavenge, it may not have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4768
    // happened because of a JNI critical section. We probably need
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4769
    // a policy for deciding whether we can in that case wait until
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4770
    // the critical section releases and then do the remark following
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4771
    // the scavenge, and skip it here. In the absence of that policy,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4772
    // or of an indication of whether the scavenge did indeed occur,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4773
    // we cannot rely on TLAB's having been filled and must do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4774
    // so here just in case a scavenge did not happen.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4775
    gch->ensure_parsability(false);  // fill TLAB's, but no need to retire them
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4776
    // Update the saved marks which may affect the root scans.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4777
    gch->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4778
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4779
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4780
      COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4781
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4782
      // Note on the role of the mod union table:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4783
      // Since the marker in "markFromRoots" marks concurrently with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4784
      // mutators, it is possible for some reachable objects not to have been
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4785
      // scanned. For instance, an only reference to an object A was
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4786
      // placed in object B after the marker scanned B. Unless B is rescanned,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4787
      // A would be collected. Such updates to references in marked objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4788
      // are detected via the mod union table which is the set of all cards
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4789
      // dirtied since the first checkpoint in this GC cycle and prior to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4790
      // the most recent young generation GC, minus those cleaned up by the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4791
      // concurrent precleaning.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4792
      if (CMSParallelRemarkEnabled && ParallelGCThreads > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4793
        TraceTime t("Rescan (parallel) ", PrintGCDetails, false, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4794
        do_remark_parallel();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4795
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4796
        TraceTime t("Rescan (non-parallel) ", PrintGCDetails, false,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4797
                    gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4798
        do_remark_non_parallel();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4799
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4800
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4801
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4802
    assert(!asynch, "Can't have init_mark_was_synchronous in asynch mode");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4803
    // The initial mark was stop-world, so there's no rescanning to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4804
    // do; go straight on to the next step below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4805
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4806
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4807
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4808
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4809
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4810
    NOT_PRODUCT(TraceTime ts("refProcessingWork", PrintGCDetails, false, gclog_or_tty);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4811
    refProcessingWork(asynch, clear_all_soft_refs);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4812
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4813
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4814
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4815
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  4816
  if (should_unload_classes()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4817
    CodeCache::gc_epilogue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4818
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4819
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4820
  // If we encountered any (marking stack / work queue) overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4821
  // events during the current CMS cycle, take appropriate
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4822
  // remedial measures, where possible, so as to try and avoid
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4823
  // recurrence of that condition.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4824
  assert(_markStack.isEmpty(), "No grey objects");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4825
  size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw +
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4826
                     _ser_kac_ovflw;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4827
  if (ser_ovflw > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4828
    if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4829
      gclog_or_tty->print_cr("Marking stack overflow (benign) "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4830
        "(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4831
        _ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4832
        _ser_kac_ovflw);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4833
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4834
    _markStack.expand();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4835
    _ser_pmc_remark_ovflw = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4836
    _ser_pmc_preclean_ovflw = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4837
    _ser_kac_ovflw = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4838
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4839
  if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4840
    if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4841
      gclog_or_tty->print_cr("Work queue overflow (benign) "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4842
        "(pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4843
        _par_pmc_remark_ovflw, _par_kac_ovflw);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4844
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4845
    _par_pmc_remark_ovflw = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4846
    _par_kac_ovflw = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4847
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4848
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4849
     if (_markStack._hit_limit > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4850
       gclog_or_tty->print_cr(" (benign) Hit max stack size limit ("SIZE_FORMAT")",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4851
                              _markStack._hit_limit);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4852
     }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4853
     if (_markStack._failed_double > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4854
       gclog_or_tty->print_cr(" (benign) Failed stack doubling ("SIZE_FORMAT"),"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4855
                              " current capacity "SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4856
                              _markStack._failed_double,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4857
                              _markStack.capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4858
     }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4859
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4860
  _markStack._hit_limit = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4861
  _markStack._failed_double = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4862
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4863
  if ((VerifyAfterGC || VerifyDuringGC) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4864
      GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4865
    verify_after_remark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4866
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4867
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4868
  // Change under the freelistLocks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4869
  _collectorState = Sweeping;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4870
  // Call isAllClear() under bitMapLock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4871
  assert(_modUnionTable.isAllClear(), "Should be clear by end of the"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4872
    " final marking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4873
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4874
    size_policy()->checkpoint_roots_final_end(gch->gc_cause());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4875
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4876
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4877
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4878
// Parallel remark task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4879
class CMSParRemarkTask: public AbstractGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4880
  CMSCollector* _collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4881
  WorkGang*     _workers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4882
  int           _n_workers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4883
  CompactibleFreeListSpace* _cms_space;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4884
  CompactibleFreeListSpace* _perm_space;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4885
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4886
  // The per-thread work queues, available here for stealing.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4887
  OopTaskQueueSet*       _task_queues;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4888
  ParallelTaskTerminator _term;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4889
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4890
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4891
  CMSParRemarkTask(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4892
                   CompactibleFreeListSpace* cms_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4893
                   CompactibleFreeListSpace* perm_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4894
                   int n_workers, WorkGang* workers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4895
                   OopTaskQueueSet* task_queues):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4896
    AbstractGangTask("Rescan roots and grey objects in parallel"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4897
    _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4898
    _cms_space(cms_space), _perm_space(perm_space),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4899
    _n_workers(n_workers),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4900
    _workers(workers),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4901
    _task_queues(task_queues),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4902
    _term(workers->total_workers(), task_queues) { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4903
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4904
  OopTaskQueueSet* task_queues() { return _task_queues; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4905
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4906
  OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4907
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4908
  ParallelTaskTerminator* terminator() { return &_term; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4909
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4910
  void work(int i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4911
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4912
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4913
  // Work method in support of parallel rescan ... of young gen spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4914
  void do_young_space_rescan(int i, Par_MarkRefsIntoAndScanClosure* cl,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4915
                             ContiguousSpace* space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4916
                             HeapWord** chunk_array, size_t chunk_top);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4917
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4918
  // ... of  dirty cards in old space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4919
  void do_dirty_card_rescan_tasks(CompactibleFreeListSpace* sp, int i,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4920
                                  Par_MarkRefsIntoAndScanClosure* cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4921
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4922
  // ... work stealing for the above
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4923
  void do_work_steal(int i, Par_MarkRefsIntoAndScanClosure* cl, int* seed);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4924
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4925
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4926
void CMSParRemarkTask::work(int i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4927
  elapsedTimer _timer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4928
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4929
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4930
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4931
  // ---------- rescan from roots --------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4932
  _timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4933
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4934
  Par_MarkRefsIntoAndScanClosure par_mrias_cl(_collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4935
    _collector->_span, _collector->ref_processor(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4936
    &(_collector->_markBitMap),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4937
    work_queue(i), &(_collector->_revisitStack));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4938
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4939
  // Rescan young gen roots first since these are likely
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4940
  // coarsely partitioned and may, on that account, constitute
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4941
  // the critical path; thus, it's best to start off that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4942
  // work first.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4943
  // ---------- young gen roots --------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4944
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4945
    DefNewGeneration* dng = _collector->_young_gen->as_DefNewGeneration();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4946
    EdenSpace* eden_space = dng->eden();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4947
    ContiguousSpace* from_space = dng->from();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4948
    ContiguousSpace* to_space   = dng->to();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4949
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4950
    HeapWord** eca = _collector->_eden_chunk_array;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4951
    size_t     ect = _collector->_eden_chunk_index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4952
    HeapWord** sca = _collector->_survivor_chunk_array;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4953
    size_t     sct = _collector->_survivor_chunk_index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4954
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4955
    assert(ect <= _collector->_eden_chunk_capacity, "out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4956
    assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4957
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4958
    do_young_space_rescan(i, &par_mrias_cl, to_space, NULL, 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4959
    do_young_space_rescan(i, &par_mrias_cl, from_space, sca, sct);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4960
    do_young_space_rescan(i, &par_mrias_cl, eden_space, eca, ect);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4961
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4962
    _timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4963
    if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4964
      gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4965
        "Finished young gen rescan work in %dth thread: %3.3f sec",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4966
        i, _timer.seconds());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4967
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4968
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4969
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4970
  // ---------- remaining roots --------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4971
  _timer.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4972
  _timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4973
  gch->gen_process_strong_roots(_collector->_cmsGen->level(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4974
                                false,     // yg was scanned above
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4975
                                true,      // collecting perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4976
                                SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4977
                                NULL, &par_mrias_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4978
  _timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4979
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4980
    gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4981
      "Finished remaining root rescan work in %dth thread: %3.3f sec",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4982
      i, _timer.seconds());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4983
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4984
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4985
  // ---------- rescan dirty cards ------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4986
  _timer.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4987
  _timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4988
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4989
  // Do the rescan tasks for each of the two spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4990
  // (cms_space and perm_space) in turn.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4991
  do_dirty_card_rescan_tasks(_cms_space, i, &par_mrias_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4992
  do_dirty_card_rescan_tasks(_perm_space, i, &par_mrias_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4993
  _timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4994
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4995
    gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4996
      "Finished dirty card rescan work in %dth thread: %3.3f sec",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4997
      i, _timer.seconds());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4998
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  4999
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5000
  // ---------- steal work from other threads ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5001
  // ---------- ... and drain overflow list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5002
  _timer.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5003
  _timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5004
  do_work_steal(i, &par_mrias_cl, _collector->hash_seed(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5005
  _timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5006
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5007
    gclog_or_tty->print_cr(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5008
      "Finished work stealing in %dth thread: %3.3f sec",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5009
      i, _timer.seconds());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5010
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5011
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5012
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5013
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5014
CMSParRemarkTask::do_young_space_rescan(int i,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5015
  Par_MarkRefsIntoAndScanClosure* cl, ContiguousSpace* space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5016
  HeapWord** chunk_array, size_t chunk_top) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5017
  // Until all tasks completed:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5018
  // . claim an unclaimed task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5019
  // . compute region boundaries corresponding to task claimed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5020
  //   using chunk_array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5021
  // . par_oop_iterate(cl) over that region
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5022
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5023
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5024
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5025
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5026
  SequentialSubTasksDone* pst = space->par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5027
  assert(pst->valid(), "Uninitialized use?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5028
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5029
  int nth_task = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5030
  int n_tasks  = pst->n_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5031
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5032
  HeapWord *start, *end;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5033
  while (!pst->is_task_claimed(/* reference */ nth_task)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5034
    // We claimed task # nth_task; compute its boundaries.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5035
    if (chunk_top == 0) {  // no samples were taken
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5036
      assert(nth_task == 0 && n_tasks == 1, "Can have only 1 EdenSpace task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5037
      start = space->bottom();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5038
      end   = space->top();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5039
    } else if (nth_task == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5040
      start = space->bottom();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5041
      end   = chunk_array[nth_task];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5042
    } else if (nth_task < (jint)chunk_top) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5043
      assert(nth_task >= 1, "Control point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5044
      start = chunk_array[nth_task - 1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5045
      end   = chunk_array[nth_task];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5046
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5047
      assert(nth_task == (jint)chunk_top, "Control point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5048
      start = chunk_array[chunk_top - 1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5049
      end   = space->top();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5050
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5051
    MemRegion mr(start, end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5052
    // Verify that mr is in space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5053
    assert(mr.is_empty() || space->used_region().contains(mr),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5054
           "Should be in space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5055
    // Verify that "start" is an object boundary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5056
    assert(mr.is_empty() || oop(mr.start())->is_oop(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5057
           "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5058
    space->par_oop_iterate(mr, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5059
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5060
  pst->all_tasks_completed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5061
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5062
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5063
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5064
CMSParRemarkTask::do_dirty_card_rescan_tasks(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5065
  CompactibleFreeListSpace* sp, int i,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5066
  Par_MarkRefsIntoAndScanClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5067
  // Until all tasks completed:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5068
  // . claim an unclaimed task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5069
  // . compute region boundaries corresponding to task claimed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5070
  // . transfer dirty bits ct->mut for that region
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5071
  // . apply rescanclosure to dirty mut bits for that region
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5072
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5073
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5074
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5075
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5076
  OopTaskQueue* work_q = work_queue(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5077
  ModUnionClosure modUnionClosure(&(_collector->_modUnionTable));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5078
  // CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! CAUTION!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5079
  // CAUTION: This closure has state that persists across calls to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5080
  // the work method dirty_range_iterate_clear() in that it has
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5081
  // imbedded in it a (subtype of) UpwardsObjectClosure. The
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5082
  // use of that state in the imbedded UpwardsObjectClosure instance
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5083
  // assumes that the cards are always iterated (even if in parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5084
  // by several threads) in monotonically increasing order per each
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5085
  // thread. This is true of the implementation below which picks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5086
  // card ranges (chunks) in monotonically increasing order globally
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5087
  // and, a-fortiori, in monotonically increasing order per thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5088
  // (the latter order being a subsequence of the former).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5089
  // If the work code below is ever reorganized into a more chaotic
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5090
  // work-partitioning form than the current "sequential tasks"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5091
  // paradigm, the use of that persistent state will have to be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5092
  // revisited and modified appropriately. See also related
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5093
  // bug 4756801 work on which should examine this code to make
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5094
  // sure that the changes there do not run counter to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5095
  // assumptions made here and necessary for correctness and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5096
  // efficiency. Note also that this code might yield inefficient
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5097
  // behaviour in the case of very large objects that span one or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5098
  // more work chunks. Such objects would potentially be scanned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5099
  // several times redundantly. Work on 4756801 should try and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5100
  // address that performance anomaly if at all possible. XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5101
  MemRegion  full_span  = _collector->_span;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5102
  CMSBitMap* bm    = &(_collector->_markBitMap);     // shared
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5103
  CMSMarkStack* rs = &(_collector->_revisitStack);   // shared
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5104
  MarkFromDirtyCardsClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5105
    greyRescanClosure(_collector, full_span, // entire span of interest
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5106
                      sp, bm, work_q, rs, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5107
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5108
  SequentialSubTasksDone* pst = sp->conc_par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5109
  assert(pst->valid(), "Uninitialized use?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5110
  int nth_task = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5111
  const int alignment = CardTableModRefBS::card_size * BitsPerWord;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5112
  MemRegion span = sp->used_region();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5113
  HeapWord* start_addr = span.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5114
  HeapWord* end_addr = (HeapWord*)round_to((intptr_t)span.end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5115
                                           alignment);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5116
  const size_t chunk_size = sp->rescan_task_size(); // in HeapWord units
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5117
  assert((HeapWord*)round_to((intptr_t)start_addr, alignment) ==
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5118
         start_addr, "Check alignment");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5119
  assert((size_t)round_to((intptr_t)chunk_size, alignment) ==
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5120
         chunk_size, "Check alignment");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5121
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5122
  while (!pst->is_task_claimed(/* reference */ nth_task)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5123
    // Having claimed the nth_task, compute corresponding mem-region,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5124
    // which is a-fortiori aligned correctly (i.e. at a MUT bopundary).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5125
    // The alignment restriction ensures that we do not need any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5126
    // synchronization with other gang-workers while setting or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5127
    // clearing bits in thus chunk of the MUT.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5128
    MemRegion this_span = MemRegion(start_addr + nth_task*chunk_size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5129
                                    start_addr + (nth_task+1)*chunk_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5130
    // The last chunk's end might be way beyond end of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5131
    // used region. In that case pull back appropriately.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5132
    if (this_span.end() > end_addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5133
      this_span.set_end(end_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5134
      assert(!this_span.is_empty(), "Program logic (calculation of n_tasks)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5135
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5136
    // Iterate over the dirty cards covering this chunk, marking them
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5137
    // precleaned, and setting the corresponding bits in the mod union
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5138
    // table. Since we have been careful to partition at Card and MUT-word
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5139
    // boundaries no synchronization is needed between parallel threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5140
    _collector->_ct->ct_bs()->dirty_card_iterate(this_span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5141
                                                 &modUnionClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5142
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5143
    // Having transferred these marks into the modUnionTable,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5144
    // rescan the marked objects on the dirty cards in the modUnionTable.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5145
    // Even if this is at a synchronous collection, the initial marking
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5146
    // may have been done during an asynchronous collection so there
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5147
    // may be dirty bits in the mod-union table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5148
    _collector->_modUnionTable.dirty_range_iterate_clear(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5149
                  this_span, &greyRescanClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5150
    _collector->_modUnionTable.verifyNoOneBitsInRange(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5151
                                 this_span.start(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5152
                                 this_span.end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5153
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5154
  pst->all_tasks_completed();  // declare that i am done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5155
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5156
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5157
// . see if we can share work_queues with ParNew? XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5158
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5159
CMSParRemarkTask::do_work_steal(int i, Par_MarkRefsIntoAndScanClosure* cl,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5160
                                int* seed) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5161
  OopTaskQueue* work_q = work_queue(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5162
  NOT_PRODUCT(int num_steals = 0;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5163
  oop obj_to_scan;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5164
  CMSBitMap* bm = &(_collector->_markBitMap);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5165
  size_t num_from_overflow_list =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5166
           MIN2((size_t)work_q->max_elems()/4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5167
                (size_t)ParGCDesiredObjsFromOverflowList);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5168
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5169
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5170
    // Completely finish any left over work from (an) earlier round(s)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5171
    cl->trim_queue(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5172
    // Now check if there's any work in the overflow list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5173
    if (_collector->par_take_from_overflow_list(num_from_overflow_list,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5174
                                                work_q)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5175
      // found something in global overflow list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5176
      // not yet ready to go stealing work from others.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5177
      // We'd like to assert(work_q->size() != 0, ...)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5178
      // because we just took work from the overflow list,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5179
      // but of course we can't since all of that could have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5180
      // been already stolen from us.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5181
      // "He giveth and He taketh away."
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5182
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5183
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5184
    // Verify that we have no work before we resort to stealing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5185
    assert(work_q->size() == 0, "Have work, shouldn't steal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5186
    // Try to steal from other queues that have work
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5187
    if (task_queues()->steal(i, seed, /* reference */ obj_to_scan)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5188
      NOT_PRODUCT(num_steals++;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5189
      assert(obj_to_scan->is_oop(), "Oops, not an oop!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5190
      assert(bm->isMarked((HeapWord*)obj_to_scan), "Stole an unmarked oop?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5191
      // Do scanning work
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5192
      obj_to_scan->oop_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5193
      // Loop around, finish this work, and try to steal some more
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5194
    } else if (terminator()->offer_termination()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5195
        break;  // nirvana from the infinite cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5196
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5197
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5198
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5199
    if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5200
      gclog_or_tty->print("\n\t(%d: stole %d oops)", i, num_steals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5201
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5202
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5203
  assert(work_q->size() == 0 && _collector->overflow_list_is_empty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5204
         "Else our work is not yet done");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5205
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5206
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5207
// Return a thread-local PLAB recording array, as appropriate.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5208
void* CMSCollector::get_data_recorder(int thr_num) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5209
  if (_survivor_plab_array != NULL &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5210
      (CMSPLABRecordAlways ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5211
       (_collectorState > Marking && _collectorState < FinalMarking))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5212
    assert(thr_num < (int)ParallelGCThreads, "thr_num is out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5213
    ChunkArray* ca = &_survivor_plab_array[thr_num];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5214
    ca->reset();   // clear it so that fresh data is recorded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5215
    return (void*) ca;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5216
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5217
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5218
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5219
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5220
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5221
// Reset all the thread-local PLAB recording arrays
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5222
void CMSCollector::reset_survivor_plab_arrays() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5223
  for (uint i = 0; i < ParallelGCThreads; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5224
    _survivor_plab_array[i].reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5225
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5226
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5227
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5228
// Merge the per-thread plab arrays into the global survivor chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5229
// array which will provide the partitioning of the survivor space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5230
// for CMS rescan.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5231
void CMSCollector::merge_survivor_plab_arrays(ContiguousSpace* surv) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5232
  assert(_survivor_plab_array  != NULL, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5233
  assert(_survivor_chunk_array != NULL, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5234
  assert(_collectorState == FinalMarking, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5235
  for (uint j = 0; j < ParallelGCThreads; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5236
    _cursor[j] = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5237
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5238
  HeapWord* top = surv->top();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5239
  size_t i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5240
  for (i = 0; i < _survivor_chunk_capacity; i++) {  // all sca entries
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5241
    HeapWord* min_val = top;          // Higher than any PLAB address
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5242
    uint      min_tid = 0;            // position of min_val this round
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5243
    for (uint j = 0; j < ParallelGCThreads; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5244
      ChunkArray* cur_sca = &_survivor_plab_array[j];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5245
      if (_cursor[j] == cur_sca->end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5246
        continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5247
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5248
      assert(_cursor[j] < cur_sca->end(), "ctl pt invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5249
      HeapWord* cur_val = cur_sca->nth(_cursor[j]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5250
      assert(surv->used_region().contains(cur_val), "Out of bounds value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5251
      if (cur_val < min_val) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5252
        min_tid = j;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5253
        min_val = cur_val;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5254
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5255
        assert(cur_val < top, "All recorded addresses should be less");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5256
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5257
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5258
    // At this point min_val and min_tid are respectively
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5259
    // the least address in _survivor_plab_array[j]->nth(_cursor[j])
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5260
    // and the thread (j) that witnesses that address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5261
    // We record this address in the _survivor_chunk_array[i]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5262
    // and increment _cursor[min_tid] prior to the next round i.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5263
    if (min_val == top) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5264
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5265
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5266
    _survivor_chunk_array[i] = min_val;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5267
    _cursor[min_tid]++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5268
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5269
  // We are all done; record the size of the _survivor_chunk_array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5270
  _survivor_chunk_index = i; // exclusive: [0, i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5271
  if (PrintCMSStatistics > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5272
    gclog_or_tty->print(" (Survivor:" SIZE_FORMAT "chunks) ", i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5273
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5274
  // Verify that we used up all the recorded entries
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5275
  #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5276
    size_t total = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5277
    for (uint j = 0; j < ParallelGCThreads; j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5278
      assert(_cursor[j] == _survivor_plab_array[j].end(), "Ctl pt invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5279
      total += _cursor[j];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5280
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5281
    assert(total == _survivor_chunk_index, "Ctl Pt Invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5282
    // Check that the merged array is in sorted order
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5283
    if (total > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5284
      for (size_t i = 0; i < total - 1; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5285
        if (PrintCMSStatistics > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5286
          gclog_or_tty->print(" (chunk" SIZE_FORMAT ":" INTPTR_FORMAT ") ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5287
                              i, _survivor_chunk_array[i]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5288
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5289
        assert(_survivor_chunk_array[i] < _survivor_chunk_array[i+1],
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5290
               "Not sorted");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5291
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5292
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5293
  #endif // ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5294
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5295
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5296
// Set up the space's par_seq_tasks structure for work claiming
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5297
// for parallel rescan of young gen.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5298
// See ParRescanTask where this is currently used.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5299
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5300
CMSCollector::
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5301
initialize_sequential_subtasks_for_young_gen_rescan(int n_threads) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5302
  assert(n_threads > 0, "Unexpected n_threads argument");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5303
  DefNewGeneration* dng = (DefNewGeneration*)_young_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5304
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5305
  // Eden space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5306
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5307
    SequentialSubTasksDone* pst = dng->eden()->par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5308
    assert(!pst->valid(), "Clobbering existing data?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5309
    // Each valid entry in [0, _eden_chunk_index) represents a task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5310
    size_t n_tasks = _eden_chunk_index + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5311
    assert(n_tasks == 1 || _eden_chunk_array != NULL, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5312
    pst->set_par_threads(n_threads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5313
    pst->set_n_tasks((int)n_tasks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5314
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5315
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5316
  // Merge the survivor plab arrays into _survivor_chunk_array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5317
  if (_survivor_plab_array != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5318
    merge_survivor_plab_arrays(dng->from());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5319
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5320
    assert(_survivor_chunk_index == 0, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5321
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5322
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5323
  // To space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5324
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5325
    SequentialSubTasksDone* pst = dng->to()->par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5326
    assert(!pst->valid(), "Clobbering existing data?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5327
    pst->set_par_threads(n_threads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5328
    pst->set_n_tasks(1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5329
    assert(pst->valid(), "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5330
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5331
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5332
  // From space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5333
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5334
    SequentialSubTasksDone* pst = dng->from()->par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5335
    assert(!pst->valid(), "Clobbering existing data?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5336
    size_t n_tasks = _survivor_chunk_index + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5337
    assert(n_tasks == 1 || _survivor_chunk_array != NULL, "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5338
    pst->set_par_threads(n_threads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5339
    pst->set_n_tasks((int)n_tasks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5340
    assert(pst->valid(), "Error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5341
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5342
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5343
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5344
// Parallel version of remark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5345
void CMSCollector::do_remark_parallel() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5346
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5347
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5348
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5349
  int n_workers = workers->total_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5350
  CompactibleFreeListSpace* cms_space  = _cmsGen->cmsSpace();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5351
  CompactibleFreeListSpace* perm_space = _permGen->cmsSpace();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5352
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5353
  CMSParRemarkTask tsk(this,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5354
    cms_space, perm_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5355
    n_workers, workers, task_queues());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5356
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5357
  // Set up for parallel process_strong_roots work.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5358
  gch->set_par_threads(n_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5359
  gch->change_strong_roots_parity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5360
  // We won't be iterating over the cards in the card table updating
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5361
  // the younger_gen cards, so we shouldn't call the following else
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5362
  // the verification code as well as subsequent younger_refs_iterate
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5363
  // code would get confused. XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5364
  // gch->rem_set()->prepare_for_younger_refs_iterate(true); // parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5365
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5366
  // The young gen rescan work will not be done as part of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5367
  // process_strong_roots (which currently doesn't knw how to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5368
  // parallelize such a scan), but rather will be broken up into
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5369
  // a set of parallel tasks (via the sampling that the [abortable]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5370
  // preclean phase did of EdenSpace, plus the [two] tasks of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5371
  // scanning the [two] survivor spaces. Further fine-grain
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5372
  // parallelization of the scanning of the survivor spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5373
  // themselves, and of precleaning of the younger gen itself
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5374
  // is deferred to the future.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5375
  initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5376
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5377
  // The dirty card rescan work is broken up into a "sequence"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5378
  // of parallel tasks (per constituent space) that are dynamically
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5379
  // claimed by the parallel threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5380
  cms_space->initialize_sequential_subtasks_for_rescan(n_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5381
  perm_space->initialize_sequential_subtasks_for_rescan(n_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5382
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5383
  // It turns out that even when we're using 1 thread, doing the work in a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5384
  // separate thread causes wide variance in run times.  We can't help this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5385
  // in the multi-threaded case, but we special-case n=1 here to get
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5386
  // repeatable measurements of the 1-thread overhead of the parallel code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5387
  if (n_workers > 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5388
    // Make refs discovery MT-safe
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5389
    ReferenceProcessorMTMutator mt(ref_processor(), true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5390
    workers->run_task(&tsk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5391
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5392
    tsk.work(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5393
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5394
  gch->set_par_threads(0);  // 0 ==> non-parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5395
  // restore, single-threaded for now, any preserved marks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5396
  // as a result of work_q overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5397
  restore_preserved_marks_if_any();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5398
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5399
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5400
// Non-parallel version of remark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5401
void CMSCollector::do_remark_non_parallel() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5402
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5403
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5404
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5405
  MarkRefsIntoAndScanClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5406
    mrias_cl(_span, ref_processor(), &_markBitMap, &_modUnionTable,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5407
             &_markStack, &_revisitStack, this,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5408
             false /* should_yield */, false /* not precleaning */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5409
  MarkFromDirtyCardsClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5410
    markFromDirtyCardsClosure(this, _span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5411
                              NULL,  // space is set further below
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5412
                              &_markBitMap, &_markStack, &_revisitStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5413
                              &mrias_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5414
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5415
    TraceTime t("grey object rescan", PrintGCDetails, false, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5416
    // Iterate over the dirty cards, marking them precleaned, and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5417
    // setting the corresponding bits in the mod union table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5418
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5419
      ModUnionClosure modUnionClosure(&_modUnionTable);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5420
      _ct->ct_bs()->dirty_card_iterate(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5421
                      _cmsGen->used_region(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5422
                      &modUnionClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5423
      _ct->ct_bs()->dirty_card_iterate(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5424
                      _permGen->used_region(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5425
                      &modUnionClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5426
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5427
    // Having transferred these marks into the modUnionTable, we just need
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5428
    // to rescan the marked objects on the dirty cards in the modUnionTable.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5429
    // The initial marking may have been done during an asynchronous
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5430
    // collection so there may be dirty bits in the mod-union table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5431
    const int alignment =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5432
      CardTableModRefBS::card_size * BitsPerWord;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5433
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5434
      // ... First handle dirty cards in CMS gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5435
      markFromDirtyCardsClosure.set_space(_cmsGen->cmsSpace());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5436
      MemRegion ur = _cmsGen->used_region();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5437
      HeapWord* lb = ur.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5438
      HeapWord* ub = (HeapWord*)round_to((intptr_t)ur.end(), alignment);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5439
      MemRegion cms_span(lb, ub);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5440
      _modUnionTable.dirty_range_iterate_clear(cms_span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5441
                                               &markFromDirtyCardsClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5442
      verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5443
      if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5444
        gclog_or_tty->print(" (re-scanned "SIZE_FORMAT" dirty cards in cms gen) ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5445
          markFromDirtyCardsClosure.num_dirty_cards());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5446
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5447
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5448
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5449
      // .. and then repeat for dirty cards in perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5450
      markFromDirtyCardsClosure.set_space(_permGen->cmsSpace());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5451
      MemRegion ur = _permGen->used_region();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5452
      HeapWord* lb = ur.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5453
      HeapWord* ub = (HeapWord*)round_to((intptr_t)ur.end(), alignment);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5454
      MemRegion perm_span(lb, ub);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5455
      _modUnionTable.dirty_range_iterate_clear(perm_span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5456
                                               &markFromDirtyCardsClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5457
      verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5458
      if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5459
        gclog_or_tty->print(" (re-scanned "SIZE_FORMAT" dirty cards in perm gen) ",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5460
          markFromDirtyCardsClosure.num_dirty_cards());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5461
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5462
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5463
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5464
  if (VerifyDuringGC &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5465
      GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5466
    HandleMark hm;  // Discard invalid handles created during verification
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5467
    Universe::verify(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5468
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5469
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5470
    TraceTime t("root rescan", PrintGCDetails, false, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5471
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5472
    verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5473
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5474
    gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5475
    gch->gen_process_strong_roots(_cmsGen->level(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5476
                                  true,  // younger gens as roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5477
                                  true,  // collecting perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5478
                                  SharedHeap::ScanningOption(roots_scanning_options()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5479
                                  NULL, &mrias_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5480
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5481
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5482
  // Restore evacuated mark words, if any, used for overflow list links
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5483
  if (!CMSOverflowEarlyRestoration) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5484
    restore_preserved_marks_if_any();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5485
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5486
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5487
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5488
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5489
////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5490
// Parallel Reference Processing Task Proxy Class
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5491
////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5492
class CMSRefProcTaskProxy: public AbstractGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5493
  typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5494
  CMSCollector*          _collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5495
  CMSBitMap*             _mark_bit_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5496
  MemRegion              _span;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5497
  OopTaskQueueSet*       _task_queues;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5498
  ParallelTaskTerminator _term;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5499
  ProcessTask&           _task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5500
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5501
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5502
  CMSRefProcTaskProxy(ProcessTask&     task,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5503
                      CMSCollector*    collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5504
                      const MemRegion& span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5505
                      CMSBitMap*       mark_bit_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5506
                      int              total_workers,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5507
                      OopTaskQueueSet* task_queues):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5508
    AbstractGangTask("Process referents by policy in parallel"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5509
    _task(task),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5510
    _collector(collector), _span(span), _mark_bit_map(mark_bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5511
    _task_queues(task_queues),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5512
    _term(total_workers, task_queues)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5513
    { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5514
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5515
  OopTaskQueueSet* task_queues() { return _task_queues; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5516
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5517
  OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5518
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5519
  ParallelTaskTerminator* terminator() { return &_term; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5520
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5521
  void do_work_steal(int i,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5522
                     CMSParDrainMarkingStackClosure* drain,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5523
                     CMSParKeepAliveClosure* keep_alive,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5524
                     int* seed);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5525
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5526
  virtual void work(int i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5527
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5528
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5529
void CMSRefProcTaskProxy::work(int i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5530
  CMSParKeepAliveClosure par_keep_alive(_collector, _span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5531
                                        _mark_bit_map, work_queue(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5532
  CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5533
                                                 _mark_bit_map, work_queue(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5534
  CMSIsAliveClosure is_alive_closure(_mark_bit_map);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5535
  _task.work(i, is_alive_closure, par_keep_alive, par_drain_stack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5536
  if (_task.marks_oops_alive()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5537
    do_work_steal(i, &par_drain_stack, &par_keep_alive,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5538
                  _collector->hash_seed(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5539
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5540
  assert(work_queue(i)->size() == 0, "work_queue should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5541
  assert(_collector->_overflow_list == NULL, "non-empty _overflow_list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5542
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5543
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5544
class CMSRefEnqueueTaskProxy: public AbstractGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5545
  typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5546
  EnqueueTask& _task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5547
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5548
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5549
  CMSRefEnqueueTaskProxy(EnqueueTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5550
    : AbstractGangTask("Enqueue reference objects in parallel"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5551
      _task(task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5552
  { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5553
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5554
  virtual void work(int i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5555
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5556
    _task.work(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5557
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5558
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5559
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5560
CMSParKeepAliveClosure::CMSParKeepAliveClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5561
  MemRegion span, CMSBitMap* bit_map, OopTaskQueue* work_queue):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5562
   _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5563
   _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5564
   _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5565
   _work_queue(work_queue),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5566
   _mark_and_push(collector, span, bit_map, work_queue),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5567
   _low_water_mark(MIN2((uint)(work_queue->max_elems()/4),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5568
                        (uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads)))
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5569
{ }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5570
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5571
// . see if we can share work_queues with ParNew? XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5572
void CMSRefProcTaskProxy::do_work_steal(int i,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5573
  CMSParDrainMarkingStackClosure* drain,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5574
  CMSParKeepAliveClosure* keep_alive,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5575
  int* seed) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5576
  OopTaskQueue* work_q = work_queue(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5577
  NOT_PRODUCT(int num_steals = 0;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5578
  oop obj_to_scan;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5579
  size_t num_from_overflow_list =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5580
           MIN2((size_t)work_q->max_elems()/4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5581
                (size_t)ParGCDesiredObjsFromOverflowList);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5582
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5583
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5584
    // Completely finish any left over work from (an) earlier round(s)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5585
    drain->trim_queue(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5586
    // Now check if there's any work in the overflow list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5587
    if (_collector->par_take_from_overflow_list(num_from_overflow_list,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5588
                                                work_q)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5589
      // Found something in global overflow list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5590
      // not yet ready to go stealing work from others.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5591
      // We'd like to assert(work_q->size() != 0, ...)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5592
      // because we just took work from the overflow list,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5593
      // but of course we can't, since all of that might have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5594
      // been already stolen from us.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5595
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5596
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5597
    // Verify that we have no work before we resort to stealing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5598
    assert(work_q->size() == 0, "Have work, shouldn't steal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5599
    // Try to steal from other queues that have work
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5600
    if (task_queues()->steal(i, seed, /* reference */ obj_to_scan)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5601
      NOT_PRODUCT(num_steals++;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5602
      assert(obj_to_scan->is_oop(), "Oops, not an oop!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5603
      assert(_mark_bit_map->isMarked((HeapWord*)obj_to_scan), "Stole an unmarked oop?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5604
      // Do scanning work
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5605
      obj_to_scan->oop_iterate(keep_alive);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5606
      // Loop around, finish this work, and try to steal some more
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5607
    } else if (terminator()->offer_termination()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5608
      break;  // nirvana from the infinite cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5609
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5610
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5611
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5612
    if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5613
      gclog_or_tty->print("\n\t(%d: stole %d oops)", i, num_steals);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5614
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5615
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5616
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5617
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5618
void CMSRefProcTaskExecutor::execute(ProcessTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5619
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5620
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5621
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5622
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5623
  int n_workers = workers->total_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5624
  CMSRefProcTaskProxy rp_task(task, &_collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5625
                              _collector.ref_processor()->span(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5626
                              _collector.markBitMap(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5627
                              n_workers, _collector.task_queues());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5628
  workers->run_task(&rp_task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5629
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5630
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5631
void CMSRefProcTaskExecutor::execute(EnqueueTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5632
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5633
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5634
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5635
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5636
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5637
  CMSRefEnqueueTaskProxy enq_task(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5638
  workers->run_task(&enq_task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5639
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5640
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5641
void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5642
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5643
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5644
  HandleMark   hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5645
  ReferencePolicy* soft_ref_policy;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5646
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5647
  assert(!ref_processor()->enqueuing_is_done(), "Enqueuing should not be complete");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5648
  // Process weak references.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5649
  if (clear_all_soft_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5650
    soft_ref_policy = new AlwaysClearPolicy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5651
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5652
#ifdef COMPILER2
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5653
    soft_ref_policy = new LRUMaxHeapPolicy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5654
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5655
    soft_ref_policy = new LRUCurrentHeapPolicy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5656
#endif // COMPILER2
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5657
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5658
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5659
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5660
  ReferenceProcessor* rp = ref_processor();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5661
  assert(rp->span().equals(_span), "Spans should be equal");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5662
  CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5663
                                          &_markStack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5664
  CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5665
                                _span, &_markBitMap, &_markStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5666
                                &cmsKeepAliveClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5667
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5668
    TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5669
    if (rp->processing_is_mt()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5670
      CMSRefProcTaskExecutor task_executor(*this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5671
      rp->process_discovered_references(soft_ref_policy,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5672
                                        &_is_alive_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5673
                                        &cmsKeepAliveClosure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5674
                                        &cmsDrainMarkingStackClosure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5675
                                        &task_executor);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5676
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5677
      rp->process_discovered_references(soft_ref_policy,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5678
                                        &_is_alive_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5679
                                        &cmsKeepAliveClosure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5680
                                        &cmsDrainMarkingStackClosure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5681
                                        NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5682
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5683
    verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5684
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5685
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  5686
  if (should_unload_classes()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5687
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5688
      TraceTime t("class unloading", PrintGCDetails, false, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5689
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5690
      // Follow SystemDictionary roots and unload classes
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5691
      bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5692
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5693
      // Follow CodeCache roots and unload any methods marked for unloading
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5694
      CodeCache::do_unloading(&_is_alive_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5695
                              &cmsKeepAliveClosure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5696
                              purged_class);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5697
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5698
      cmsDrainMarkingStackClosure.do_void();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5699
      verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5700
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5701
      // Update subklass/sibling/implementor links in KlassKlass descendants
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5702
      assert(!_revisitStack.isEmpty(), "revisit stack should not be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5703
      oop k;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5704
      while ((k = _revisitStack.pop()) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5705
        ((Klass*)(oopDesc*)k)->follow_weak_klass_links(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5706
                       &_is_alive_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5707
                       &cmsKeepAliveClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5708
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5709
      assert(!ClassUnloading ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5710
             (_markStack.isEmpty() && overflow_list_is_empty()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5711
             "Should not have found new reachable objects");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5712
      assert(_revisitStack.isEmpty(), "revisit stack should have been drained");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5713
      cmsDrainMarkingStackClosure.do_void();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5714
      verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5715
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5716
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5717
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5718
      TraceTime t("scrub symbol & string tables", PrintGCDetails, false, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5719
      // Now clean up stale oops in SymbolTable and StringTable
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5720
      SymbolTable::unlink(&_is_alive_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5721
      StringTable::unlink(&_is_alive_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5722
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5723
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5724
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5725
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5726
  // Restore any preserved marks as a result of mark stack or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5727
  // work queue overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5728
  restore_preserved_marks_if_any();  // done single-threaded for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5729
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5730
  rp->set_enqueuing_is_done(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5731
  if (rp->processing_is_mt()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5732
    CMSRefProcTaskExecutor task_executor(*this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5733
    rp->enqueue_discovered_references(&task_executor);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5734
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5735
    rp->enqueue_discovered_references(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5736
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5737
  rp->verify_no_references_recorded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5738
  assert(!rp->discovery_enabled(), "should have been disabled");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5739
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5740
  // JVMTI object tagging is based on JNI weak refs. If any of these
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5741
  // refs were cleared then JVMTI needs to update its maps and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5742
  // maybe post ObjectFrees to agents.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5743
  JvmtiExport::cms_ref_processing_epilogue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5744
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5745
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5746
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5747
void CMSCollector::check_correct_thread_executing() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5748
  Thread* t = Thread::current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5749
  // Only the VM thread or the CMS thread should be here.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5750
  assert(t->is_ConcurrentGC_thread() || t->is_VM_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5751
         "Unexpected thread type");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5752
  // If this is the vm thread, the foreground process
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5753
  // should not be waiting.  Note that _foregroundGCIsActive is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5754
  // true while the foreground collector is waiting.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5755
  if (_foregroundGCShouldWait) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5756
    // We cannot be the VM thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5757
    assert(t->is_ConcurrentGC_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5758
           "Should be CMS thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5759
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5760
    // We can be the CMS thread only if we are in a stop-world
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5761
    // phase of CMS collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5762
    if (t->is_ConcurrentGC_thread()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5763
      assert(_collectorState == InitialMarking ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5764
             _collectorState == FinalMarking,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5765
             "Should be a stop-world phase");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5766
      // The CMS thread should be holding the CMS_token.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5767
      assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5768
             "Potential interference with concurrently "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5769
             "executing VM thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5770
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5771
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5772
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5773
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5774
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5775
void CMSCollector::sweep(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5776
  assert(_collectorState == Sweeping, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5777
  check_correct_thread_executing();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5778
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5779
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5780
  incrementSweepCount();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5781
  _sweep_timer.stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5782
  _sweep_estimate.sample(_sweep_timer.seconds());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5783
  size_policy()->avg_cms_free_at_sweep()->sample(_cmsGen->free());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5784
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5785
  // PermGen verification support: If perm gen sweeping is disabled in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5786
  // this cycle, we preserve the perm gen object "deadness" information
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5787
  // in the perm_gen_verify_bit_map. In order to do that we traverse
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5788
  // all blocks in perm gen and mark all dead objects.
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  5789
  if (verifying() && !should_unload_classes()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5790
    assert(perm_gen_verify_bit_map()->sizeInBits() != 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5791
           "Should have already been allocated");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5792
    MarkDeadObjectsClosure mdo(this, _permGen->cmsSpace(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5793
                               markBitMap(), perm_gen_verify_bit_map());
180
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5794
    if (asynch) {
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5795
      CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(),
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5796
                               bitMapLock());
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5797
      _permGen->cmsSpace()->blk_iterate(&mdo);
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5798
    } else {
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5799
      // In the case of synchronous sweep, we already have
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5800
      // the requisite locks/tokens.
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5801
      _permGen->cmsSpace()->blk_iterate(&mdo);
09c6284b0f5e 6621144: CMS: assertion failure "is_cms_thread == Thread::current()->is_ConcurrentGC_thread()"
ysr
parents: 1
diff changeset
  5802
    }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5803
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5804
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5805
  if (asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5806
    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5807
    CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5808
    // First sweep the old gen then the perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5809
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5810
      CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5811
                               bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5812
      sweepWork(_cmsGen, asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5813
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5814
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5815
    // Now repeat for perm gen
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  5816
    if (should_unload_classes()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5817
      CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5818
                             bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5819
      sweepWork(_permGen, asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5820
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5821
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5822
    // Update Universe::_heap_*_at_gc figures.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5823
    // We need all the free list locks to make the abstract state
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5824
    // transition from Sweeping to Resetting. See detailed note
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5825
    // further below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5826
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5827
      CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5828
                               _permGen->freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5829
      // Update heap occupancy information which is used as
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5830
      // input to soft ref clearing policy at the next gc.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5831
      Universe::update_heap_info_at_gc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5832
      _collectorState = Resizing;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5833
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5834
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5835
    // already have needed locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5836
    sweepWork(_cmsGen,  asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5837
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  5838
    if (should_unload_classes()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5839
      sweepWork(_permGen, asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5840
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5841
    // Update heap occupancy information which is used as
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5842
    // input to soft ref clearing policy at the next gc.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5843
    Universe::update_heap_info_at_gc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5844
    _collectorState = Resizing;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5845
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5846
  verify_work_stacks_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5847
  verify_overflow_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5848
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5849
  _sweep_timer.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5850
  _sweep_timer.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5851
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5852
  update_time_of_last_gc(os::javaTimeMillis());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5853
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5854
  // NOTE on abstract state transitions:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5855
  // Mutators allocate-live and/or mark the mod-union table dirty
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5856
  // based on the state of the collection.  The former is done in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5857
  // the interval [Marking, Sweeping] and the latter in the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5858
  // [Marking, Sweeping).  Thus the transitions into the Marking state
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5859
  // and out of the Sweeping state must be synchronously visible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5860
  // globally to the mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5861
  // The transition into the Marking state happens with the world
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5862
  // stopped so the mutators will globally see it.  Sweeping is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5863
  // done asynchronously by the background collector so the transition
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5864
  // from the Sweeping state to the Resizing state must be done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5865
  // under the freelistLock (as is the check for whether to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5866
  // allocate-live and whether to dirty the mod-union table).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5867
  assert(_collectorState == Resizing, "Change of collector state to"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5868
    " Resizing must be done under the freelistLocks (plural)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5869
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5870
  // Now that sweeping has been completed, if the GCH's
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5871
  // incremental_collection_will_fail flag is set, clear it,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5872
  // thus inviting a younger gen collection to promote into
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5873
  // this generation. If such a promotion may still fail,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5874
  // the flag will be set again when a young collection is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5875
  // attempted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5876
  // I think the incremental_collection_will_fail flag's use
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5877
  // is specific to a 2 generation collection policy, so i'll
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5878
  // assert that that's the configuration we are operating within.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5879
  // The use of the flag can and should be generalized appropriately
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5880
  // in the future to deal with a general n-generation system.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5881
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5882
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5883
  assert(gch->collector_policy()->is_two_generation_policy(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5884
         "Resetting of incremental_collection_will_fail flag"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5885
         " may be incorrect otherwise");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5886
  gch->clear_incremental_collection_will_fail();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5887
  gch->update_full_collections_completed(_collection_count_start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5888
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5889
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5890
// FIX ME!!! Looks like this belongs in CFLSpace, with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5891
// CMSGen merely delegating to it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5892
void ConcurrentMarkSweepGeneration::setNearLargestChunk() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5893
  double nearLargestPercent = 0.999;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5894
  HeapWord*  minAddr        = _cmsSpace->bottom();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5895
  HeapWord*  largestAddr    =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5896
    (HeapWord*) _cmsSpace->dictionary()->findLargestDict();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5897
  if (largestAddr == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5898
    // The dictionary appears to be empty.  In this case
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5899
    // try to coalesce at the end of the heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5900
    largestAddr = _cmsSpace->end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5901
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5902
  size_t largestOffset     = pointer_delta(largestAddr, minAddr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5903
  size_t nearLargestOffset =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5904
    (size_t)((double)largestOffset * nearLargestPercent) - MinChunkSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5905
  _cmsSpace->set_nearLargestChunk(minAddr + nearLargestOffset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5906
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5907
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5908
bool ConcurrentMarkSweepGeneration::isNearLargestChunk(HeapWord* addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5909
  return addr >= _cmsSpace->nearLargestChunk();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5910
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5911
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5912
FreeChunk* ConcurrentMarkSweepGeneration::find_chunk_at_end() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5913
  return _cmsSpace->find_chunk_at_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5914
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5915
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5916
void ConcurrentMarkSweepGeneration::update_gc_stats(int current_level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5917
                                                    bool full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5918
  // The next lower level has been collected.  Gather any statistics
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5919
  // that are of interest at this point.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5920
  if (!full && (current_level + 1) == level()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5921
    // Gather statistics on the young generation collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5922
    collector()->stats().record_gc0_end(used());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5923
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5924
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5925
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5926
CMSAdaptiveSizePolicy* ConcurrentMarkSweepGeneration::size_policy() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5927
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5928
  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5929
    "Wrong type of heap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5930
  CMSAdaptiveSizePolicy* sp = (CMSAdaptiveSizePolicy*)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5931
    gch->gen_policy()->size_policy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5932
  assert(sp->is_gc_cms_adaptive_size_policy(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5933
    "Wrong type of size policy");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5934
  return sp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5935
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5936
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5937
void ConcurrentMarkSweepGeneration::rotate_debug_collection_type() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5938
  if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5939
    gclog_or_tty->print("Rotate from %d ", _debug_collection_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5940
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5941
  _debug_collection_type = (CollectionTypes) (_debug_collection_type + 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5942
  _debug_collection_type =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5943
    (CollectionTypes) (_debug_collection_type % Unknown_collection_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5944
  if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5945
    gclog_or_tty->print_cr("to %d ", _debug_collection_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5946
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5947
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5948
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5949
void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5950
  bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5951
  // We iterate over the space(s) underlying this generation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5952
  // checking the mark bit map to see if the bits corresponding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5953
  // to specific blocks are marked or not. Blocks that are
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5954
  // marked are live and are not swept up. All remaining blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5955
  // are swept up, with coalescing on-the-fly as we sweep up
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5956
  // contiguous free and/or garbage blocks:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5957
  // We need to ensure that the sweeper synchronizes with allocators
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5958
  // and stop-the-world collectors. In particular, the following
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5959
  // locks are used:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5960
  // . CMS token: if this is held, a stop the world collection cannot occur
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5961
  // . freelistLock: if this is held no allocation can occur from this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5962
  //                 generation by another thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5963
  // . bitMapLock: if this is held, no other thread can access or update
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5964
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5965
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5966
  // Note that we need to hold the freelistLock if we use
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5967
  // block iterate below; else the iterator might go awry if
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5968
  // a mutator (or promotion) causes block contents to change
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5969
  // (for instance if the allocator divvies up a block).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5970
  // If we hold the free list lock, for all practical purposes
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5971
  // young generation GC's can't occur (they'll usually need to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5972
  // promote), so we might as well prevent all young generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5973
  // GC's while we do a sweeping step. For the same reason, we might
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5974
  // as well take the bit map lock for the entire duration
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5975
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5976
  // check that we hold the requisite locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5977
  assert(have_cms_token(), "Should hold cms token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5978
  assert(   (asynch && ConcurrentMarkSweepThread::cms_thread_has_cms_token())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5979
         || (!asynch && ConcurrentMarkSweepThread::vm_thread_has_cms_token()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5980
        "Should possess CMS token to sweep");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5981
  assert_lock_strong(gen->freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5982
  assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5983
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5984
  assert(!_sweep_timer.is_active(), "Was switched off in an outer context");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5985
  gen->cmsSpace()->beginSweepFLCensus((float)(_sweep_timer.seconds()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5986
                                      _sweep_estimate.padded_average());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5987
  gen->setNearLargestChunk();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5988
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5989
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5990
    SweepClosure sweepClosure(this, gen, &_markBitMap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5991
                            CMSYield && asynch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5992
    gen->cmsSpace()->blk_iterate_careful(&sweepClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5993
    // We need to free-up/coalesce garbage/blocks from a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5994
    // co-terminal free run. This is done in the SweepClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5995
    // destructor; so, do not remove this scope, else the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5996
    // end-of-sweep-census below will be off by a little bit.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5997
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5998
  gen->cmsSpace()->sweep_completed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  5999
  gen->cmsSpace()->endSweepFLCensus(sweepCount());
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  6000
  if (should_unload_classes()) {                // unloaded classes this cycle,
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  6001
    _concurrent_cycles_since_last_unload = 0;   // ... reset count
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  6002
  } else {                                      // did not unload classes,
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  6003
    _concurrent_cycles_since_last_unload++;     // ... increment count
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  6004
  }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6005
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6006
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6007
// Reset CMS data structures (for now just the marking bit map)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6008
// preparatory for the next cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6009
void CMSCollector::reset(bool asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6010
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6011
  CMSAdaptiveSizePolicy* sp = size_policy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6012
  AdaptiveSizePolicyOutput(sp, gch->total_collections());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6013
  if (asynch) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6014
    CMSTokenSyncWithLocks ts(true, bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6015
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6016
    // If the state is not "Resetting", the foreground  thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6017
    // has done a collection and the resetting.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6018
    if (_collectorState != Resetting) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6019
      assert(_collectorState == Idling, "The state should only change"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6020
        " because the foreground collector has finished the collection");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6021
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6022
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6023
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6024
    // Clear the mark bitmap (no grey objects to start with)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6025
    // for the next cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6026
    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6027
    CMSPhaseAccounting cmspa(this, "reset", !PrintGCDetails);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6028
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6029
    HeapWord* curAddr = _markBitMap.startWord();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6030
    while (curAddr < _markBitMap.endWord()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6031
      size_t remaining  = pointer_delta(_markBitMap.endWord(), curAddr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6032
      MemRegion chunk(curAddr, MIN2(CMSBitMapYieldQuantum, remaining));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6033
      _markBitMap.clear_large_range(chunk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6034
      if (ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6035
          !foregroundGCIsActive() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6036
          CMSYield) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6037
        assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6038
               "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6039
        assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6040
        bitMapLock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6041
        ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6042
        ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6043
        stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6044
        if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6045
          incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6046
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6047
        icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6048
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6049
        // See the comment in coordinator_yield()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6050
        for (unsigned i = 0; i < CMSYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6051
                        ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6052
                        !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6053
          os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6054
          ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6055
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6056
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6057
        ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6058
        bitMapLock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6059
        startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6060
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6061
      curAddr = chunk.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6062
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6063
    _collectorState = Idling;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6064
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6065
    // already have the lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6066
    assert(_collectorState == Resetting, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6067
    assert_lock_strong(bitMapLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6068
    _markBitMap.clear_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6069
    _collectorState = Idling;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6070
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6071
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6072
  // Stop incremental mode after a cycle completes, so that any future cycles
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6073
  // are triggered by allocation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6074
  stop_icms();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6075
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6076
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6077
    if (RotateCMSCollectionTypes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6078
      _cmsGen->rotate_debug_collection_type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6079
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6080
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6081
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6082
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6083
void CMSCollector::do_CMS_operation(CMS_op_type op) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6084
  gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6085
  TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6086
  TraceTime t("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6087
  TraceCollectorStats tcs(counters());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6088
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6089
  switch (op) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6090
    case CMS_op_checkpointRootsInitial: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6091
      checkpointRootsInitial(true);       // asynch
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6092
      if (PrintGC) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6093
        _cmsGen->printOccupancy("initial-mark");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6094
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6095
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6096
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6097
    case CMS_op_checkpointRootsFinal: {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6098
      checkpointRootsFinal(true,    // asynch
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6099
                           false,   // !clear_all_soft_refs
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6100
                           false);  // !init_mark_was_synchronous
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6101
      if (PrintGC) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6102
        _cmsGen->printOccupancy("remark");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6103
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6104
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6105
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6106
    default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6107
      fatal("No such CMS_op");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6108
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6109
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6110
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6111
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6112
size_t const CMSCollector::skip_header_HeapWords() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6113
  return FreeChunk::header_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6114
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6115
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6116
// Try and collect here conditions that should hold when
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6117
// CMS thread is exiting. The idea is that the foreground GC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6118
// thread should not be blocked if it wants to terminate
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6119
// the CMS thread and yet continue to run the VM for a while
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6120
// after that.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6121
void CMSCollector::verify_ok_to_terminate() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6122
  assert(Thread::current()->is_ConcurrentGC_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6123
         "should be called by CMS thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6124
  assert(!_foregroundGCShouldWait, "should be false");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6125
  // We could check here that all the various low-level locks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6126
  // are not held by the CMS thread, but that is overkill; see
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6127
  // also CMSThread::verify_ok_to_terminate() where the CGC_lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6128
  // is checked.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6129
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6130
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6131
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6132
size_t CMSCollector::block_size_using_printezis_bits(HeapWord* addr) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6133
  assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6134
         "missing Printezis mark?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6135
  HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6136
  size_t size = pointer_delta(nextOneAddr + 1, addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6137
  assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6138
         "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6139
  assert(size >= 3, "Necessary for Printezis marks to work");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6140
  return size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6141
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6142
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6143
// A variant of the above (block_size_using_printezis_bits()) except
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6144
// that we return 0 if the P-bits are not yet set.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6145
size_t CMSCollector::block_size_if_printezis_bits(HeapWord* addr) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6146
  if (_markBitMap.isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6147
    assert(_markBitMap.isMarked(addr + 1), "Missing Printezis bit?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6148
    HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6149
    size_t size = pointer_delta(nextOneAddr + 1, addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6150
    assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6151
           "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6152
    assert(size >= 3, "Necessary for Printezis marks to work");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6153
    return size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6154
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6155
    assert(!_markBitMap.isMarked(addr + 1), "Bit map inconsistency?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6156
    return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6157
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6158
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6160
HeapWord* CMSCollector::next_card_start_after_block(HeapWord* addr) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6161
  size_t sz = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6162
  oop p = (oop)addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6163
  if (p->klass() != NULL && p->is_parsable()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6164
    sz = CompactibleFreeListSpace::adjustObjectSize(p->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6165
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6166
    sz = block_size_using_printezis_bits(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6167
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6168
  assert(sz > 0, "size must be nonzero");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6169
  HeapWord* next_block = addr + sz;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6170
  HeapWord* next_card  = (HeapWord*)round_to((uintptr_t)next_block,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6171
                                             CardTableModRefBS::card_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6172
  assert(round_down((uintptr_t)addr,      CardTableModRefBS::card_size) <
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6173
         round_down((uintptr_t)next_card, CardTableModRefBS::card_size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6174
         "must be different cards");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6175
  return next_card;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6176
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6177
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6178
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6179
// CMS Bit Map Wrapper /////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6180
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6181
// Construct a CMS bit map infrastructure, but don't create the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6182
// bit vector itself. That is done by a separate call CMSBitMap::allocate()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6183
// further below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6184
CMSBitMap::CMSBitMap(int shifter, int mutex_rank, const char* mutex_name):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6185
  _bm(NULL,0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6186
  _shifter(shifter),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6187
  _lock(mutex_rank >= 0 ? new Mutex(mutex_rank, mutex_name, true) : NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6188
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6189
  _bmStartWord = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6190
  _bmWordSize  = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6191
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6192
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6193
bool CMSBitMap::allocate(MemRegion mr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6194
  _bmStartWord = mr.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6195
  _bmWordSize  = mr.word_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6196
  ReservedSpace brs(ReservedSpace::allocation_align_size_up(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6197
                     (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6198
  if (!brs.is_reserved()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6199
    warning("CMS bit map allocation failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6200
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6201
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6202
  // For now we'll just commit all of the bit map up fromt.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6203
  // Later on we'll try to be more parsimonious with swap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6204
  if (!_virtual_space.initialize(brs, brs.size())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6205
    warning("CMS bit map backing store failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6206
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6207
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6208
  assert(_virtual_space.committed_size() == brs.size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6209
         "didn't reserve backing store for all of CMS bit map?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6210
  _bm.set_map((uintptr_t*)_virtual_space.low());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6211
  assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >=
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6212
         _bmWordSize, "inconsistency in bit map sizing");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6213
  _bm.set_size(_bmWordSize >> _shifter);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6214
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6215
  // bm.clear(); // can we rely on getting zero'd memory? verify below
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6216
  assert(isAllClear(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6217
         "Expected zero'd memory from ReservedSpace constructor");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6218
  assert(_bm.size() == heapWordDiffToOffsetDiff(sizeInWords()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6219
         "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6220
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6221
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6222
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6223
void CMSBitMap::dirty_range_iterate_clear(MemRegion mr, MemRegionClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6224
  HeapWord *next_addr, *end_addr, *last_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6225
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6226
  assert(covers(mr), "out-of-range error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6227
  // XXX assert that start and end are appropriately aligned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6228
  for (next_addr = mr.start(), end_addr = mr.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6229
       next_addr < end_addr; next_addr = last_addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6230
    MemRegion dirty_region = getAndClearMarkedRegion(next_addr, end_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6231
    last_addr = dirty_region.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6232
    if (!dirty_region.is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6233
      cl->do_MemRegion(dirty_region);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6234
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6235
      assert(last_addr == end_addr, "program logic");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6236
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6237
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6238
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6239
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6240
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6241
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6242
void CMSBitMap::assert_locked() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6243
  CMSLockVerifier::assert_locked(lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6244
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6245
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6246
bool CMSBitMap::covers(MemRegion mr) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6247
  // assert(_bm.map() == _virtual_space.low(), "map inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6248
  assert((size_t)_bm.size() == (_bmWordSize >> _shifter),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6249
         "size inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6250
  return (mr.start() >= _bmStartWord) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6251
         (mr.end()   <= endWord());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6252
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6253
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6254
bool CMSBitMap::covers(HeapWord* start, size_t size) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6255
    return (start >= _bmStartWord && (start + size) <= endWord());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6256
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6257
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6258
void CMSBitMap::verifyNoOneBitsInRange(HeapWord* left, HeapWord* right) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6259
  // verify that there are no 1 bits in the interval [left, right)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6260
  FalseBitMapClosure falseBitMapClosure;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6261
  iterate(&falseBitMapClosure, left, right);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6262
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6263
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6264
void CMSBitMap::region_invariant(MemRegion mr)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6265
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6266
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6267
  // mr = mr.intersection(MemRegion(_bmStartWord, _bmWordSize));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6268
  assert(!mr.is_empty(), "unexpected empty region");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6269
  assert(covers(mr), "mr should be covered by bit map");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6270
  // convert address range into offset range
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6271
  size_t start_ofs = heapWordToOffset(mr.start());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6272
  // Make sure that end() is appropriately aligned
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6273
  assert(mr.end() == (HeapWord*)round_to((intptr_t)mr.end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6274
                        (1 << (_shifter+LogHeapWordSize))),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6275
         "Misaligned mr.end()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6276
  size_t end_ofs   = heapWordToOffset(mr.end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6277
  assert(end_ofs > start_ofs, "Should mark at least one bit");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6278
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6279
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6280
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6281
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6282
bool CMSMarkStack::allocate(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6283
  // allocate a stack of the requisite depth
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6284
  ReservedSpace rs(ReservedSpace::allocation_align_size_up(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6285
                   size * sizeof(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6286
  if (!rs.is_reserved()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6287
    warning("CMSMarkStack allocation failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6288
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6289
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6290
  if (!_virtual_space.initialize(rs, rs.size())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6291
    warning("CMSMarkStack backing store failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6292
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6293
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6294
  assert(_virtual_space.committed_size() == rs.size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6295
         "didn't reserve backing store for all of CMS stack?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6296
  _base = (oop*)(_virtual_space.low());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6297
  _index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6298
  _capacity = size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6299
  NOT_PRODUCT(_max_depth = 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6300
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6301
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6302
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6303
// XXX FIX ME !!! In the MT case we come in here holding a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6304
// leaf lock. For printing we need to take a further lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6305
// which has lower rank. We need to recallibrate the two
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6306
// lock-ranks involved in order to be able to rpint the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6307
// messages below. (Or defer the printing to the caller.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6308
// For now we take the expedient path of just disabling the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6309
// messages for the problematic case.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6310
void CMSMarkStack::expand() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6311
  assert(_capacity <= CMSMarkStackSizeMax, "stack bigger than permitted");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6312
  if (_capacity == CMSMarkStackSizeMax) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6313
    if (_hit_limit++ == 0 && !CMSConcurrentMTEnabled && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6314
      // We print a warning message only once per CMS cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6315
      gclog_or_tty->print_cr(" (benign) Hit CMSMarkStack max size limit");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6316
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6317
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6318
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6319
  // Double capacity if possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6320
  size_t new_capacity = MIN2(_capacity*2, CMSMarkStackSizeMax);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6321
  // Do not give up existing stack until we have managed to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6322
  // get the double capacity that we desired.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6323
  ReservedSpace rs(ReservedSpace::allocation_align_size_up(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6324
                   new_capacity * sizeof(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6325
  if (rs.is_reserved()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6326
    // Release the backing store associated with old stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6327
    _virtual_space.release();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6328
    // Reinitialize virtual space for new stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6329
    if (!_virtual_space.initialize(rs, rs.size())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6330
      fatal("Not enough swap for expanded marking stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6331
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6332
    _base = (oop*)(_virtual_space.low());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6333
    _index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6334
    _capacity = new_capacity;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6335
  } else if (_failed_double++ == 0 && !CMSConcurrentMTEnabled && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6336
    // Failed to double capacity, continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6337
    // we print a detail message only once per CMS cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6338
    gclog_or_tty->print(" (benign) Failed to expand marking stack from "SIZE_FORMAT"K to "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6339
            SIZE_FORMAT"K",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6340
            _capacity / K, new_capacity / K);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6341
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6342
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6343
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6344
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6345
// Closures
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6346
// XXX: there seems to be a lot of code  duplication here;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6347
// should refactor and consolidate common code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6348
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6349
// This closure is used to mark refs into the CMS generation in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6350
// the CMS bit map. Called at the first checkpoint. This closure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6351
// assumes that we do not need to re-mark dirty cards; if the CMS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6352
// generation on which this is used is not an oldest (modulo perm gen)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6353
// generation then this will lose younger_gen cards!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6354
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6355
MarkRefsIntoClosure::MarkRefsIntoClosure(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6356
  MemRegion span, CMSBitMap* bitMap, bool should_do_nmethods):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6357
    _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6358
    _bitMap(bitMap),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6359
    _should_do_nmethods(should_do_nmethods)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6360
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6361
    assert(_ref_processor == NULL, "deliberately left NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6362
    assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6363
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6364
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6365
void MarkRefsIntoClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6366
  // if p points into _span, then mark corresponding bit in _markBitMap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6367
  oop thisOop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6368
  if (thisOop != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6369
    assert(thisOop->is_oop(), "expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6370
    HeapWord* addr = (HeapWord*)thisOop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6371
    if (_span.contains(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6372
      // this should be made more efficient
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6373
      _bitMap->mark(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6374
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6375
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6376
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6377
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6378
// A variant of the above, used for CMS marking verification.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6379
MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6380
  MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6381
  bool should_do_nmethods):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6382
    _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6383
    _verification_bm(verification_bm),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6384
    _cms_bm(cms_bm),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6385
    _should_do_nmethods(should_do_nmethods) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6386
    assert(_ref_processor == NULL, "deliberately left NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6387
    assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6388
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6389
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6390
void MarkRefsIntoVerifyClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6391
  // if p points into _span, then mark corresponding bit in _markBitMap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6392
  oop this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6393
  if (this_oop != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6394
    assert(this_oop->is_oop(), "expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6395
    HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6396
    if (_span.contains(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6397
      _verification_bm->mark(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6398
      if (!_cms_bm->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6399
        oop(addr)->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6400
        gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6401
        fatal("... aborting");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6402
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6403
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6404
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6405
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6406
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6407
//////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6408
// MarkRefsIntoAndScanClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6409
//////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6410
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6411
MarkRefsIntoAndScanClosure::MarkRefsIntoAndScanClosure(MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6412
                                                       ReferenceProcessor* rp,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6413
                                                       CMSBitMap* bit_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6414
                                                       CMSBitMap* mod_union_table,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6415
                                                       CMSMarkStack*  mark_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6416
                                                       CMSMarkStack*  revisit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6417
                                                       CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6418
                                                       bool should_yield,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6419
                                                       bool concurrent_precleaning):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6420
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6421
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6422
  _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6423
  _mark_stack(mark_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6424
  _pushAndMarkClosure(collector, span, rp, bit_map, mod_union_table,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6425
                      mark_stack, revisit_stack, concurrent_precleaning),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6426
  _yield(should_yield),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6427
  _concurrent_precleaning(concurrent_precleaning),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6428
  _freelistLock(NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6429
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6430
  _ref_processor = rp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6431
  assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6432
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6433
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6434
// This closure is used to mark refs into the CMS generation at the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6435
// second (final) checkpoint, and to scan and transitively follow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6436
// the unmarked oops. It is also used during the concurrent precleaning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6437
// phase while scanning objects on dirty cards in the CMS generation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6438
// The marks are made in the marking bit map and the marking stack is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6439
// used for keeping the (newly) grey objects during the scan.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6440
// The parallel version (Par_...) appears further below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6441
void MarkRefsIntoAndScanClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6442
  oop this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6443
  if (this_oop != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6444
    assert(this_oop->is_oop(), "expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6445
    HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6446
    assert(_mark_stack->isEmpty(), "post-condition (eager drainage)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6447
    assert(_collector->overflow_list_is_empty(), "should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6448
    if (_span.contains(addr) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6449
        !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6450
      // mark bit map (object is now grey)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6451
      _bit_map->mark(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6452
      // push on marking stack (stack should be empty), and drain the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6453
      // stack by applying this closure to the oops in the oops popped
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6454
      // from the stack (i.e. blacken the grey objects)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6455
      bool res = _mark_stack->push(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6456
      assert(res, "Should have space to push on empty stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6457
      do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6458
        oop new_oop = _mark_stack->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6459
        assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6460
        assert(new_oop->is_parsable(), "Found unparsable oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6461
        assert(_bit_map->isMarked((HeapWord*)new_oop),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6462
               "only grey objects on this stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6463
        // iterate over the oops in this oop, marking and pushing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6464
        // the ones in CMS heap (i.e. in _span).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6465
        new_oop->oop_iterate(&_pushAndMarkClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6466
        // check if it's time to yield
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6467
        do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6468
      } while (!_mark_stack->isEmpty() ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6469
               (!_concurrent_precleaning && take_from_overflow_list()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6470
        // if marking stack is empty, and we are not doing this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6471
        // during precleaning, then check the overflow list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6472
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6473
    assert(_mark_stack->isEmpty(), "post-condition (eager drainage)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6474
    assert(_collector->overflow_list_is_empty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6475
           "overflow list was drained above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6476
    // We could restore evacuated mark words, if any, used for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6477
    // overflow list links here because the overflow list is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6478
    // provably empty here. That would reduce the maximum
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6479
    // size requirements for preserved_{oop,mark}_stack.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6480
    // But we'll just postpone it until we are all done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6481
    // so we can just stream through.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6482
    if (!_concurrent_precleaning && CMSOverflowEarlyRestoration) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6483
      _collector->restore_preserved_marks_if_any();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6484
      assert(_collector->no_preserved_marks(), "No preserved marks");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6485
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6486
    assert(!CMSOverflowEarlyRestoration || _collector->no_preserved_marks(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6487
           "All preserved marks should have been restored above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6488
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6489
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6490
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6491
void MarkRefsIntoAndScanClosure::do_yield_work() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6492
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6493
         "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6494
  assert_lock_strong(_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6495
  assert_lock_strong(_bit_map->lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6496
  // relinquish the free_list_lock and bitMaplock()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6497
  _bit_map->lock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6498
  _freelistLock->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6499
  ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6500
  ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6501
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6502
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6503
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6504
    _collector->incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6505
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6506
  _collector->icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6507
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6508
  // See the comment in coordinator_yield()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6509
  for (unsigned i = 0; i < CMSYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6510
                       ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6511
                       !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6512
    os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6513
    ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6514
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6515
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6516
  ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6517
  _freelistLock->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6518
  _bit_map->lock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6519
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6520
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6521
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6522
///////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6523
// Par_MarkRefsIntoAndScanClosure: a parallel version of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6524
//                                 MarkRefsIntoAndScanClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6525
///////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6526
Par_MarkRefsIntoAndScanClosure::Par_MarkRefsIntoAndScanClosure(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6527
  CMSCollector* collector, MemRegion span, ReferenceProcessor* rp,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6528
  CMSBitMap* bit_map, OopTaskQueue* work_queue, CMSMarkStack*  revisit_stack):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6529
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6530
  _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6531
  _work_queue(work_queue),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6532
  _low_water_mark(MIN2((uint)(work_queue->max_elems()/4),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6533
                       (uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads))),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6534
  _par_pushAndMarkClosure(collector, span, rp, bit_map, work_queue,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6535
                          revisit_stack)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6536
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6537
  _ref_processor = rp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6538
  assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6539
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6540
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6541
// This closure is used to mark refs into the CMS generation at the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6542
// second (final) checkpoint, and to scan and transitively follow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6543
// the unmarked oops. The marks are made in the marking bit map and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6544
// the work_queue is used for keeping the (newly) grey objects during
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6545
// the scan phase whence they are also available for stealing by parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6546
// threads. Since the marking bit map is shared, updates are
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6547
// synchronized (via CAS).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6548
void Par_MarkRefsIntoAndScanClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6549
  oop this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6550
  if (this_oop != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6551
    // Ignore mark word because this could be an already marked oop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6552
    // that may be chained at the end of the overflow list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6553
    assert(this_oop->is_oop(true /* ignore mark word */), "expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6554
    HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6555
    if (_span.contains(addr) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6556
        !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6557
      // mark bit map (object will become grey):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6558
      // It is possible for several threads to be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6559
      // trying to "claim" this object concurrently;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6560
      // the unique thread that succeeds in marking the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6561
      // object first will do the subsequent push on
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6562
      // to the work queue (or overflow list).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6563
      if (_bit_map->par_mark(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6564
        // push on work_queue (which may not be empty), and trim the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6565
        // queue to an appropriate length by applying this closure to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6566
        // the oops in the oops popped from the stack (i.e. blacken the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6567
        // grey objects)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6568
        bool res = _work_queue->push(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6569
        assert(res, "Low water mark should be less than capacity?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6570
        trim_queue(_low_water_mark);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6571
      } // Else, another thread claimed the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6572
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6573
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6574
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6575
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6576
// This closure is used to rescan the marked objects on the dirty cards
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6577
// in the mod union table and the card table proper.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6578
size_t ScanMarkedObjectsAgainCarefullyClosure::do_object_careful_m(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6579
  oop p, MemRegion mr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6580
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6581
  size_t size = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6582
  HeapWord* addr = (HeapWord*)p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6583
  DEBUG_ONLY(_collector->verify_work_stacks_empty();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6584
  assert(_span.contains(addr), "we are scanning the CMS generation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6585
  // check if it's time to yield
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6586
  if (do_yield_check()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6587
    // We yielded for some foreground stop-world work,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6588
    // and we have been asked to abort this ongoing preclean cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6589
    return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6590
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6591
  if (_bitMap->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6592
    // it's marked; is it potentially uninitialized?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6593
    if (p->klass() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6594
      if (CMSPermGenPrecleaningEnabled && !p->is_parsable()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6595
        // Signal precleaning to redirty the card since
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6596
        // the klass pointer is already installed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6597
        assert(size == 0, "Initial value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6598
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6599
        assert(p->is_parsable(), "must be parsable.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6600
        // an initialized object; ignore mark word in verification below
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6601
        // since we are running concurrent with mutators
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6602
        assert(p->is_oop(true), "should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6603
        if (p->is_objArray()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6604
          // objArrays are precisely marked; restrict scanning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6605
          // to dirty cards only.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6606
          size = p->oop_iterate(_scanningClosure, mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6607
          assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6608
                 "adjustObjectSize should be the identity for array sizes, "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6609
                 "which are necessarily larger than minimum object size of "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6610
                 "two heap words");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6611
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6612
          // A non-array may have been imprecisely marked; we need
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6613
          // to scan object in its entirety.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6614
          size = CompactibleFreeListSpace::adjustObjectSize(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6615
                   p->oop_iterate(_scanningClosure));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6616
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6617
        #ifdef DEBUG
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6618
          size_t direct_size =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6619
            CompactibleFreeListSpace::adjustObjectSize(p->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6620
          assert(size == direct_size, "Inconsistency in size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6621
          assert(size >= 3, "Necessary for Printezis marks to work");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6622
          if (!_bitMap->isMarked(addr+1)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6623
            _bitMap->verifyNoOneBitsInRange(addr+2, addr+size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6624
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6625
            _bitMap->verifyNoOneBitsInRange(addr+2, addr+size-1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6626
            assert(_bitMap->isMarked(addr+size-1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6627
                   "inconsistent Printezis mark");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6628
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6629
        #endif // DEBUG
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6630
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6631
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6632
      // an unitialized object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6633
      assert(_bitMap->isMarked(addr+1), "missing Printezis mark?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6634
      HeapWord* nextOneAddr = _bitMap->getNextMarkedWordAddress(addr + 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6635
      size = pointer_delta(nextOneAddr + 1, addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6636
      assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6637
             "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6638
      // Note that pre-cleaning needn't redirty the card. OopDesc::set_klass()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6639
      // will dirty the card when the klass pointer is installed in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6640
      // object (signalling the completion of initialization).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6641
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6642
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6643
    // Either a not yet marked object or an uninitialized object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6644
    if (p->klass() == NULL || !p->is_parsable()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6645
      // An uninitialized object, skip to the next card, since
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6646
      // we may not be able to read its P-bits yet.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6647
      assert(size == 0, "Initial value");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6648
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6649
      // An object not (yet) reached by marking: we merely need to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6650
      // compute its size so as to go look at the next block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6651
      assert(p->is_oop(true), "should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6652
      size = CompactibleFreeListSpace::adjustObjectSize(p->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6653
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6654
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6655
  DEBUG_ONLY(_collector->verify_work_stacks_empty();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6656
  return size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6657
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6658
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6659
void ScanMarkedObjectsAgainCarefullyClosure::do_yield_work() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6660
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6661
         "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6662
  assert_lock_strong(_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6663
  assert_lock_strong(_bitMap->lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6664
  // relinquish the free_list_lock and bitMaplock()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6665
  _bitMap->lock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6666
  _freelistLock->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6667
  ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6668
  ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6669
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6670
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6671
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6672
    _collector->incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6673
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6674
  _collector->icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6675
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6676
  // See the comment in coordinator_yield()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6677
  for (unsigned i = 0; i < CMSYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6678
                       ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6679
                       !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6680
    os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6681
    ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6682
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6683
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6684
  ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6685
  _freelistLock->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6686
  _bitMap->lock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6687
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6688
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6689
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6690
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6691
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6692
// SurvivorSpacePrecleanClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6693
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6694
// This (single-threaded) closure is used to preclean the oops in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6695
// the survivor spaces.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6696
size_t SurvivorSpacePrecleanClosure::do_object_careful(oop p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6697
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6698
  HeapWord* addr = (HeapWord*)p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6699
  DEBUG_ONLY(_collector->verify_work_stacks_empty();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6700
  assert(!_span.contains(addr), "we are scanning the survivor spaces");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6701
  assert(p->klass() != NULL, "object should be initializd");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6702
  assert(p->is_parsable(), "must be parsable.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6703
  // an initialized object; ignore mark word in verification below
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6704
  // since we are running concurrent with mutators
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6705
  assert(p->is_oop(true), "should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6706
  // Note that we do not yield while we iterate over
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6707
  // the interior oops of p, pushing the relevant ones
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6708
  // on our marking stack.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6709
  size_t size = p->oop_iterate(_scanning_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6710
  do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6711
  // Observe that below, we do not abandon the preclean
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6712
  // phase as soon as we should; rather we empty the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6713
  // marking stack before returning. This is to satisfy
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6714
  // some existing assertions. In general, it may be a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6715
  // good idea to abort immediately and complete the marking
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6716
  // from the grey objects at a later time.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6717
  while (!_mark_stack->isEmpty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6718
    oop new_oop = _mark_stack->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6719
    assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6720
    assert(new_oop->is_parsable(), "Found unparsable oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6721
    assert(_bit_map->isMarked((HeapWord*)new_oop),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6722
           "only grey objects on this stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6723
    // iterate over the oops in this oop, marking and pushing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6724
    // the ones in CMS heap (i.e. in _span).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6725
    new_oop->oop_iterate(_scanning_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6726
    // check if it's time to yield
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6727
    do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6728
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6729
  unsigned int after_count =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6730
    GenCollectedHeap::heap()->total_collections();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6731
  bool abort = (_before_count != after_count) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6732
               _collector->should_abort_preclean();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6733
  return abort ? 0 : size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6734
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6735
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6736
void SurvivorSpacePrecleanClosure::do_yield_work() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6737
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6738
         "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6739
  assert_lock_strong(_bit_map->lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6740
  // Relinquish the bit map lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6741
  _bit_map->lock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6742
  ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6743
  ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6744
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6745
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6746
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6747
    _collector->incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6748
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6749
  _collector->icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6750
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6751
  // See the comment in coordinator_yield()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6752
  for (unsigned i = 0; i < CMSYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6753
                       ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6754
                       !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6755
    os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6756
    ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6757
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6758
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6759
  ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6760
  _bit_map->lock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6761
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6762
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6763
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6764
// This closure is used to rescan the marked objects on the dirty cards
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6765
// in the mod union table and the card table proper. In the parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6766
// case, although the bitMap is shared, we do a single read so the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6767
// isMarked() query is "safe".
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6768
bool ScanMarkedObjectsAgainClosure::do_object_bm(oop p, MemRegion mr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6769
  // Ignore mark word because we are running concurrent with mutators
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6770
  assert(p->is_oop_or_null(true), "expected an oop or null");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6771
  HeapWord* addr = (HeapWord*)p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6772
  assert(_span.contains(addr), "we are scanning the CMS generation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6773
  bool is_obj_array = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6774
  #ifdef DEBUG
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6775
    if (!_parallel) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6776
      assert(_mark_stack->isEmpty(), "pre-condition (eager drainage)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6777
      assert(_collector->overflow_list_is_empty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6778
             "overflow list should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6779
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6780
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6781
  #endif // DEBUG
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6782
  if (_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6783
    // Obj arrays are precisely marked, non-arrays are not;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6784
    // so we scan objArrays precisely and non-arrays in their
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6785
    // entirety.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6786
    if (p->is_objArray()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6787
      is_obj_array = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6788
      if (_parallel) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6789
        p->oop_iterate(_par_scan_closure, mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6790
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6791
        p->oop_iterate(_scan_closure, mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6792
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6793
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6794
      if (_parallel) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6795
        p->oop_iterate(_par_scan_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6796
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6797
        p->oop_iterate(_scan_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6798
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6799
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6800
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6801
  #ifdef DEBUG
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6802
    if (!_parallel) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6803
      assert(_mark_stack->isEmpty(), "post-condition (eager drainage)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6804
      assert(_collector->overflow_list_is_empty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6805
             "overflow list should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6806
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6807
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6808
  #endif // DEBUG
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6809
  return is_obj_array;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6810
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6811
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6812
MarkFromRootsClosure::MarkFromRootsClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6813
                        MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6814
                        CMSBitMap* bitMap, CMSMarkStack*  markStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6815
                        CMSMarkStack*  revisitStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6816
                        bool should_yield, bool verifying):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6817
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6818
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6819
  _bitMap(bitMap),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6820
  _mut(&collector->_modUnionTable),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6821
  _markStack(markStack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6822
  _revisitStack(revisitStack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6823
  _yield(should_yield),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6824
  _skipBits(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6825
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6826
  assert(_markStack->isEmpty(), "stack should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6827
  _finger = _bitMap->startWord();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6828
  _threshold = _finger;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6829
  assert(_collector->_restart_addr == NULL, "Sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6830
  assert(_span.contains(_finger), "Out of bounds _finger?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6831
  DEBUG_ONLY(_verifying = verifying;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6832
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6833
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6834
void MarkFromRootsClosure::reset(HeapWord* addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6835
  assert(_markStack->isEmpty(), "would cause duplicates on stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6836
  assert(_span.contains(addr), "Out of bounds _finger?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6837
  _finger = addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6838
  _threshold = (HeapWord*)round_to(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6839
                 (intptr_t)_finger, CardTableModRefBS::card_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6840
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6841
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6842
// Should revisit to see if this should be restructured for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6843
// greater efficiency.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6844
void MarkFromRootsClosure::do_bit(size_t offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6845
  if (_skipBits > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6846
    _skipBits--;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6847
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6848
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6849
  // convert offset into a HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6850
  HeapWord* addr = _bitMap->startWord() + offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6851
  assert(_bitMap->endWord() && addr < _bitMap->endWord(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6852
         "address out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6853
  assert(_bitMap->isMarked(addr), "tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6854
  if (_bitMap->isMarked(addr+1)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6855
    // this is an allocated but not yet initialized object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6856
    assert(_skipBits == 0, "tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6857
    _skipBits = 2;  // skip next two marked bits ("Printezis-marks")
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6858
    oop p = oop(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6859
    if (p->klass() == NULL || !p->is_parsable()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6860
      DEBUG_ONLY(if (!_verifying) {)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6861
        // We re-dirty the cards on which this object lies and increase
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6862
        // the _threshold so that we'll come back to scan this object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6863
        // during the preclean or remark phase. (CMSCleanOnEnter)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6864
        if (CMSCleanOnEnter) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6865
          size_t sz = _collector->block_size_using_printezis_bits(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6866
          HeapWord* start_card_addr = (HeapWord*)round_down(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6867
                                         (intptr_t)addr, CardTableModRefBS::card_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6868
          HeapWord* end_card_addr   = (HeapWord*)round_to(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6869
                                         (intptr_t)(addr+sz), CardTableModRefBS::card_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6870
          MemRegion redirty_range = MemRegion(start_card_addr, end_card_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6871
          assert(!redirty_range.is_empty(), "Arithmetical tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6872
          // Bump _threshold to end_card_addr; note that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6873
          // _threshold cannot possibly exceed end_card_addr, anyhow.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6874
          // This prevents future clearing of the card as the scan proceeds
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6875
          // to the right.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6876
          assert(_threshold <= end_card_addr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6877
                 "Because we are just scanning into this object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6878
          if (_threshold < end_card_addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6879
            _threshold = end_card_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6880
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6881
          if (p->klass() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6882
            // Redirty the range of cards...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6883
            _mut->mark_range(redirty_range);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6884
          } // ...else the setting of klass will dirty the card anyway.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6885
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6886
      DEBUG_ONLY(})
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6887
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6888
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6889
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6890
  scanOopsInOop(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6891
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6892
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6893
// We take a break if we've been at this for a while,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6894
// so as to avoid monopolizing the locks involved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6895
void MarkFromRootsClosure::do_yield_work() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6896
  // First give up the locks, then yield, then re-lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6897
  // We should probably use a constructor/destructor idiom to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6898
  // do this unlock/lock or modify the MutexUnlocker class to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6899
  // serve our purpose. XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6900
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6901
         "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6902
  assert_lock_strong(_bitMap->lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6903
  _bitMap->lock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6904
  ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6905
  ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6906
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6907
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6908
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6909
    _collector->incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6910
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6911
  _collector->icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6912
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6913
  // See the comment in coordinator_yield()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6914
  for (unsigned i = 0; i < CMSYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6915
                       ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6916
                       !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6917
    os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6918
    ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6919
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6920
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6921
  ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6922
  _bitMap->lock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6923
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6924
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6925
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6926
void MarkFromRootsClosure::scanOopsInOop(HeapWord* ptr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6927
  assert(_bitMap->isMarked(ptr), "expected bit to be set");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6928
  assert(_markStack->isEmpty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6929
         "should drain stack to limit stack usage");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6930
  // convert ptr to an oop preparatory to scanning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6931
  oop this_oop = oop(ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6932
  // Ignore mark word in verification below, since we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6933
  // may be running concurrent with mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6934
  assert(this_oop->is_oop(true), "should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6935
  assert(_finger <= ptr, "_finger runneth ahead");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6936
  // advance the finger to right end of this object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6937
  _finger = ptr + this_oop->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6938
  assert(_finger > ptr, "we just incremented it above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6939
  // On large heaps, it may take us some time to get through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6940
  // the marking phase (especially if running iCMS). During
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6941
  // this time it's possible that a lot of mutations have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6942
  // accumulated in the card table and the mod union table --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6943
  // these mutation records are redundant until we have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6944
  // actually traced into the corresponding card.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6945
  // Here, we check whether advancing the finger would make
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6946
  // us cross into a new card, and if so clear corresponding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6947
  // cards in the MUT (preclean them in the card-table in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6948
  // future).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6949
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6950
  DEBUG_ONLY(if (!_verifying) {)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6951
    // The clean-on-enter optimization is disabled by default,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6952
    // until we fix 6178663.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6953
    if (CMSCleanOnEnter && (_finger > _threshold)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6954
      // [_threshold, _finger) represents the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6955
      // of cards to be cleared  in MUT (or precleaned in card table).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6956
      // The set of cards to be cleared is all those that overlap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6957
      // with the interval [_threshold, _finger); note that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6958
      // _threshold is always kept card-aligned but _finger isn't
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6959
      // always card-aligned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6960
      HeapWord* old_threshold = _threshold;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6961
      assert(old_threshold == (HeapWord*)round_to(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6962
              (intptr_t)old_threshold, CardTableModRefBS::card_size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6963
             "_threshold should always be card-aligned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6964
      _threshold = (HeapWord*)round_to(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6965
                     (intptr_t)_finger, CardTableModRefBS::card_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6966
      MemRegion mr(old_threshold, _threshold);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6967
      assert(!mr.is_empty(), "Control point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6968
      assert(_span.contains(mr), "Should clear within span");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6969
      // XXX When _finger crosses from old gen into perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6970
      // we may be doing unnecessary cleaning; do better in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6971
      // future by detecting that condition and clearing fewer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6972
      // MUT/CT entries.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6973
      _mut->clear_range(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6974
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6975
  DEBUG_ONLY(})
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6976
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6977
  // Note: the finger doesn't advance while we drain
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6978
  // the stack below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6979
  PushOrMarkClosure pushOrMarkClosure(_collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6980
                                      _span, _bitMap, _markStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6981
                                      _revisitStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6982
                                      _finger, this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6983
  bool res = _markStack->push(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6984
  assert(res, "Empty non-zero size stack should have space for single push");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6985
  while (!_markStack->isEmpty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6986
    oop new_oop = _markStack->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6987
    // Skip verifying header mark word below because we are
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6988
    // running concurrent with mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6989
    assert(new_oop->is_oop(true), "Oops! expected to pop an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6990
    // now scan this oop's oops
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6991
    new_oop->oop_iterate(&pushOrMarkClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6992
    do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6993
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6994
  assert(_markStack->isEmpty(), "tautology, emphasizing post-condition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6995
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6996
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6997
Par_MarkFromRootsClosure::Par_MarkFromRootsClosure(CMSConcMarkingTask* task,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6998
                       CMSCollector* collector, MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  6999
                       CMSBitMap* bit_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7000
                       OopTaskQueue* work_queue,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7001
                       CMSMarkStack*  overflow_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7002
                       CMSMarkStack*  revisit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7003
                       bool should_yield):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7004
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7005
  _whole_span(collector->_span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7006
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7007
  _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7008
  _mut(&collector->_modUnionTable),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7009
  _work_queue(work_queue),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7010
  _overflow_stack(overflow_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7011
  _revisit_stack(revisit_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7012
  _yield(should_yield),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7013
  _skip_bits(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7014
  _task(task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7015
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7016
  assert(_work_queue->size() == 0, "work_queue should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7017
  _finger = span.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7018
  _threshold = _finger;     // XXX Defer clear-on-enter optimization for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7019
  assert(_span.contains(_finger), "Out of bounds _finger?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7020
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7021
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7022
// Should revisit to see if this should be restructured for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7023
// greater efficiency.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7024
void Par_MarkFromRootsClosure::do_bit(size_t offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7025
  if (_skip_bits > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7026
    _skip_bits--;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7027
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7028
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7029
  // convert offset into a HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7030
  HeapWord* addr = _bit_map->startWord() + offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7031
  assert(_bit_map->endWord() && addr < _bit_map->endWord(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7032
         "address out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7033
  assert(_bit_map->isMarked(addr), "tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7034
  if (_bit_map->isMarked(addr+1)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7035
    // this is an allocated object that might not yet be initialized
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7036
    assert(_skip_bits == 0, "tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7037
    _skip_bits = 2;  // skip next two marked bits ("Printezis-marks")
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7038
    oop p = oop(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7039
    if (p->klass() == NULL || !p->is_parsable()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7040
      // in the case of Clean-on-Enter optimization, redirty card
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7041
      // and avoid clearing card by increasing  the threshold.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7042
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7043
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7044
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7045
  scan_oops_in_oop(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7046
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7047
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7048
void Par_MarkFromRootsClosure::scan_oops_in_oop(HeapWord* ptr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7049
  assert(_bit_map->isMarked(ptr), "expected bit to be set");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7050
  // Should we assert that our work queue is empty or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7051
  // below some drain limit?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7052
  assert(_work_queue->size() == 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7053
         "should drain stack to limit stack usage");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7054
  // convert ptr to an oop preparatory to scanning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7055
  oop this_oop = oop(ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7056
  // Ignore mark word in verification below, since we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7057
  // may be running concurrent with mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7058
  assert(this_oop->is_oop(true), "should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7059
  assert(_finger <= ptr, "_finger runneth ahead");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7060
  // advance the finger to right end of this object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7061
  _finger = ptr + this_oop->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7062
  assert(_finger > ptr, "we just incremented it above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7063
  // On large heaps, it may take us some time to get through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7064
  // the marking phase (especially if running iCMS). During
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7065
  // this time it's possible that a lot of mutations have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7066
  // accumulated in the card table and the mod union table --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7067
  // these mutation records are redundant until we have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7068
  // actually traced into the corresponding card.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7069
  // Here, we check whether advancing the finger would make
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7070
  // us cross into a new card, and if so clear corresponding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7071
  // cards in the MUT (preclean them in the card-table in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7072
  // future).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7073
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7074
  // The clean-on-enter optimization is disabled by default,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7075
  // until we fix 6178663.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7076
  if (CMSCleanOnEnter && (_finger > _threshold)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7077
    // [_threshold, _finger) represents the interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7078
    // of cards to be cleared  in MUT (or precleaned in card table).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7079
    // The set of cards to be cleared is all those that overlap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7080
    // with the interval [_threshold, _finger); note that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7081
    // _threshold is always kept card-aligned but _finger isn't
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7082
    // always card-aligned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7083
    HeapWord* old_threshold = _threshold;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7084
    assert(old_threshold == (HeapWord*)round_to(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7085
            (intptr_t)old_threshold, CardTableModRefBS::card_size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7086
           "_threshold should always be card-aligned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7087
    _threshold = (HeapWord*)round_to(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7088
                   (intptr_t)_finger, CardTableModRefBS::card_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7089
    MemRegion mr(old_threshold, _threshold);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7090
    assert(!mr.is_empty(), "Control point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7091
    assert(_span.contains(mr), "Should clear within span"); // _whole_span ??
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7092
    // XXX When _finger crosses from old gen into perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7093
    // we may be doing unnecessary cleaning; do better in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7094
    // future by detecting that condition and clearing fewer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7095
    // MUT/CT entries.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7096
    _mut->clear_range(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7097
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7098
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7099
  // Note: the local finger doesn't advance while we drain
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7100
  // the stack below, but the global finger sure can and will.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7101
  HeapWord** gfa = _task->global_finger_addr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7102
  Par_PushOrMarkClosure pushOrMarkClosure(_collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7103
                                      _span, _bit_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7104
                                      _work_queue,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7105
                                      _overflow_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7106
                                      _revisit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7107
                                      _finger,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7108
                                      gfa, this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7109
  bool res = _work_queue->push(this_oop);   // overflow could occur here
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7110
  assert(res, "Will hold once we use workqueues");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7111
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7112
    oop new_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7113
    if (!_work_queue->pop_local(new_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7114
      // We emptied our work_queue; check if there's stuff that can
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7115
      // be gotten from the overflow stack.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7116
      if (CMSConcMarkingTask::get_work_from_overflow_stack(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7117
            _overflow_stack, _work_queue)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7118
        do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7119
        continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7120
      } else {  // done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7121
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7122
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7123
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7124
    // Skip verifying header mark word below because we are
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7125
    // running concurrent with mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7126
    assert(new_oop->is_oop(true), "Oops! expected to pop an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7127
    // now scan this oop's oops
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7128
    new_oop->oop_iterate(&pushOrMarkClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7129
    do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7130
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7131
  assert(_work_queue->size() == 0, "tautology, emphasizing post-condition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7132
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7133
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7134
// Yield in response to a request from VM Thread or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7135
// from mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7136
void Par_MarkFromRootsClosure::do_yield_work() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7137
  assert(_task != NULL, "sanity");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7138
  _task->yield();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7139
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7140
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7141
// A variant of the above used for verifying CMS marking work.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7142
MarkFromRootsVerifyClosure::MarkFromRootsVerifyClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7143
                        MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7144
                        CMSBitMap* verification_bm, CMSBitMap* cms_bm,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7145
                        CMSMarkStack*  mark_stack):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7146
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7147
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7148
  _verification_bm(verification_bm),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7149
  _cms_bm(cms_bm),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7150
  _mark_stack(mark_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7151
  _pam_verify_closure(collector, span, verification_bm, cms_bm,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7152
                      mark_stack)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7153
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7154
  assert(_mark_stack->isEmpty(), "stack should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7155
  _finger = _verification_bm->startWord();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7156
  assert(_collector->_restart_addr == NULL, "Sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7157
  assert(_span.contains(_finger), "Out of bounds _finger?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7158
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7160
void MarkFromRootsVerifyClosure::reset(HeapWord* addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7161
  assert(_mark_stack->isEmpty(), "would cause duplicates on stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7162
  assert(_span.contains(addr), "Out of bounds _finger?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7163
  _finger = addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7164
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7165
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7166
// Should revisit to see if this should be restructured for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7167
// greater efficiency.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7168
void MarkFromRootsVerifyClosure::do_bit(size_t offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7169
  // convert offset into a HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7170
  HeapWord* addr = _verification_bm->startWord() + offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7171
  assert(_verification_bm->endWord() && addr < _verification_bm->endWord(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7172
         "address out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7173
  assert(_verification_bm->isMarked(addr), "tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7174
  assert(_cms_bm->isMarked(addr), "tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7175
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7176
  assert(_mark_stack->isEmpty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7177
         "should drain stack to limit stack usage");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7178
  // convert addr to an oop preparatory to scanning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7179
  oop this_oop = oop(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7180
  assert(this_oop->is_oop(), "should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7181
  assert(_finger <= addr, "_finger runneth ahead");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7182
  // advance the finger to right end of this object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7183
  _finger = addr + this_oop->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7184
  assert(_finger > addr, "we just incremented it above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7185
  // Note: the finger doesn't advance while we drain
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7186
  // the stack below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7187
  bool res = _mark_stack->push(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7188
  assert(res, "Empty non-zero size stack should have space for single push");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7189
  while (!_mark_stack->isEmpty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7190
    oop new_oop = _mark_stack->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7191
    assert(new_oop->is_oop(), "Oops! expected to pop an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7192
    // now scan this oop's oops
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7193
    new_oop->oop_iterate(&_pam_verify_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7194
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7195
  assert(_mark_stack->isEmpty(), "tautology, emphasizing post-condition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7196
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7197
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7198
PushAndMarkVerifyClosure::PushAndMarkVerifyClosure(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7199
  CMSCollector* collector, MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7200
  CMSBitMap* verification_bm, CMSBitMap* cms_bm,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7201
  CMSMarkStack*  mark_stack):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7202
  OopClosure(collector->ref_processor()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7203
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7204
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7205
  _verification_bm(verification_bm),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7206
  _cms_bm(cms_bm),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7207
  _mark_stack(mark_stack)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7208
{ }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7209
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7210
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7211
// Upon stack overflow, we discard (part of) the stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7212
// remembering the least address amongst those discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7213
// in CMSCollector's _restart_address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7214
void PushAndMarkVerifyClosure::handle_stack_overflow(HeapWord* lost) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7215
  // Remember the least grey address discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7216
  HeapWord* ra = (HeapWord*)_mark_stack->least_value(lost);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7217
  _collector->lower_restart_addr(ra);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7218
  _mark_stack->reset();  // discard stack contents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7219
  _mark_stack->expand(); // expand the stack if possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7220
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7221
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7222
void PushAndMarkVerifyClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7223
  oop    this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7224
  assert(this_oop->is_oop_or_null(), "expected an oop or NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7225
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7226
  if (_span.contains(addr) && !_verification_bm->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7227
    // Oop lies in _span and isn't yet grey or black
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7228
    _verification_bm->mark(addr);            // now grey
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7229
    if (!_cms_bm->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7230
      oop(addr)->print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7231
      gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7232
      fatal("... aborting");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7233
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7234
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7235
    if (!_mark_stack->push(this_oop)) { // stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7236
      if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7237
        gclog_or_tty->print_cr("CMS marking stack overflow (benign) at "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7238
                               SIZE_FORMAT, _mark_stack->capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7239
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7240
      assert(_mark_stack->isFull(), "Else push should have succeeded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7241
      handle_stack_overflow(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7242
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7243
    // anything including and to the right of _finger
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7244
    // will be scanned as we iterate over the remainder of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7245
    // bit map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7246
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7247
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7248
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7249
PushOrMarkClosure::PushOrMarkClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7250
                     MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7251
                     CMSBitMap* bitMap, CMSMarkStack*  markStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7252
                     CMSMarkStack*  revisitStack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7253
                     HeapWord* finger, MarkFromRootsClosure* parent) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7254
  OopClosure(collector->ref_processor()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7255
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7256
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7257
  _bitMap(bitMap),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7258
  _markStack(markStack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7259
  _revisitStack(revisitStack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7260
  _finger(finger),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7261
  _parent(parent),
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  7262
  _should_remember_klasses(collector->should_unload_classes())
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7263
{ }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7264
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7265
Par_PushOrMarkClosure::Par_PushOrMarkClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7266
                     MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7267
                     CMSBitMap* bit_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7268
                     OopTaskQueue* work_queue,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7269
                     CMSMarkStack*  overflow_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7270
                     CMSMarkStack*  revisit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7271
                     HeapWord* finger,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7272
                     HeapWord** global_finger_addr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7273
                     Par_MarkFromRootsClosure* parent) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7274
  OopClosure(collector->ref_processor()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7275
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7276
  _whole_span(collector->_span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7277
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7278
  _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7279
  _work_queue(work_queue),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7280
  _overflow_stack(overflow_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7281
  _revisit_stack(revisit_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7282
  _finger(finger),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7283
  _global_finger_addr(global_finger_addr),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7284
  _parent(parent),
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  7285
  _should_remember_klasses(collector->should_unload_classes())
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7286
{ }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7287
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7288
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7289
void CMSCollector::lower_restart_addr(HeapWord* low) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7290
  assert(_span.contains(low), "Out of bounds addr");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7291
  if (_restart_addr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7292
    _restart_addr = low;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7293
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7294
    _restart_addr = MIN2(_restart_addr, low);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7295
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7296
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7297
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7298
// Upon stack overflow, we discard (part of) the stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7299
// remembering the least address amongst those discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7300
// in CMSCollector's _restart_address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7301
void PushOrMarkClosure::handle_stack_overflow(HeapWord* lost) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7302
  // Remember the least grey address discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7303
  HeapWord* ra = (HeapWord*)_markStack->least_value(lost);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7304
  _collector->lower_restart_addr(ra);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7305
  _markStack->reset();  // discard stack contents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7306
  _markStack->expand(); // expand the stack if possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7307
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7308
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7309
// Upon stack overflow, we discard (part of) the stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7310
// remembering the least address amongst those discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7311
// in CMSCollector's _restart_address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7312
void Par_PushOrMarkClosure::handle_stack_overflow(HeapWord* lost) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7313
  // We need to do this under a mutex to prevent other
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7314
  // workers from interfering with the expansion below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7315
  MutexLockerEx ml(_overflow_stack->par_lock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7316
                   Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7317
  // Remember the least grey address discarded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7318
  HeapWord* ra = (HeapWord*)_overflow_stack->least_value(lost);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7319
  _collector->lower_restart_addr(ra);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7320
  _overflow_stack->reset();  // discard stack contents
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7321
  _overflow_stack->expand(); // expand the stack if possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7322
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7323
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7324
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7325
void PushOrMarkClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7326
  oop    thisOop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7327
  // Ignore mark word because we are running concurrent with mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7328
  assert(thisOop->is_oop_or_null(true), "expected an oop or NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7329
  HeapWord* addr = (HeapWord*)thisOop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7330
  if (_span.contains(addr) && !_bitMap->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7331
    // Oop lies in _span and isn't yet grey or black
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7332
    _bitMap->mark(addr);            // now grey
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7333
    if (addr < _finger) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7334
      // the bit map iteration has already either passed, or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7335
      // sampled, this bit in the bit map; we'll need to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7336
      // use the marking stack to scan this oop's oops.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7337
      bool simulate_overflow = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7338
      NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7339
        if (CMSMarkStackOverflowALot &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7340
            _collector->simulate_overflow()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7341
          // simulate a stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7342
          simulate_overflow = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7343
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7344
      )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7345
      if (simulate_overflow || !_markStack->push(thisOop)) { // stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7346
        if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7347
          gclog_or_tty->print_cr("CMS marking stack overflow (benign) at "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7348
                                 SIZE_FORMAT, _markStack->capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7349
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7350
        assert(simulate_overflow || _markStack->isFull(), "Else push should have succeeded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7351
        handle_stack_overflow(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7352
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7353
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7354
    // anything including and to the right of _finger
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7355
    // will be scanned as we iterate over the remainder of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7356
    // bit map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7357
    do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7358
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7359
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7360
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7361
void Par_PushOrMarkClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7362
  oop    this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7363
  // Ignore mark word because we are running concurrent with mutators.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7364
  assert(this_oop->is_oop_or_null(true), "expected an oop or NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7365
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7366
  if (_whole_span.contains(addr) && !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7367
    // Oop lies in _span and isn't yet grey or black
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7368
    // We read the global_finger (volatile read) strictly after marking oop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7369
    bool res = _bit_map->par_mark(addr);    // now grey
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7370
    volatile HeapWord** gfa = (volatile HeapWord**)_global_finger_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7371
    // Should we push this marked oop on our stack?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7372
    // -- if someone else marked it, nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7373
    // -- if target oop is above global finger nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7374
    // -- if target oop is in chunk and above local finger
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7375
    //      then nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7376
    // -- else push on work queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7377
    if (   !res       // someone else marked it, they will deal with it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7378
        || (addr >= *gfa)  // will be scanned in a later task
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7379
        || (_span.contains(addr) && addr >= _finger)) { // later in this chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7380
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7381
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7382
    // the bit map iteration has already either passed, or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7383
    // sampled, this bit in the bit map; we'll need to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7384
    // use the marking stack to scan this oop's oops.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7385
    bool simulate_overflow = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7386
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7387
      if (CMSMarkStackOverflowALot &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7388
          _collector->simulate_overflow()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7389
        // simulate a stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7390
        simulate_overflow = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7391
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7392
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7393
    if (simulate_overflow ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7394
        !(_work_queue->push(this_oop) || _overflow_stack->par_push(this_oop))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7395
      // stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7396
      if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7397
        gclog_or_tty->print_cr("CMS marking stack overflow (benign) at "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7398
                               SIZE_FORMAT, _overflow_stack->capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7399
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7400
      // We cannot assert that the overflow stack is full because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7401
      // it may have been emptied since.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7402
      assert(simulate_overflow ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7403
             _work_queue->size() == _work_queue->max_elems(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7404
            "Else push should have succeeded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7405
      handle_stack_overflow(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7406
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7407
    do_yield_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7408
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7409
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7410
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7411
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7412
PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7413
                                       MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7414
                                       ReferenceProcessor* rp,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7415
                                       CMSBitMap* bit_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7416
                                       CMSBitMap* mod_union_table,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7417
                                       CMSMarkStack*  mark_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7418
                                       CMSMarkStack*  revisit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7419
                                       bool           concurrent_precleaning):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7420
  OopClosure(rp),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7421
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7422
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7423
  _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7424
  _mod_union_table(mod_union_table),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7425
  _mark_stack(mark_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7426
  _revisit_stack(revisit_stack),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7427
  _concurrent_precleaning(concurrent_precleaning),
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  7428
  _should_remember_klasses(collector->should_unload_classes())
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7429
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7430
  assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7431
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7432
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7433
// Grey object rescan during pre-cleaning and second checkpoint phases --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7434
// the non-parallel version (the parallel version appears further below.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7435
void PushAndMarkClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7436
  oop    this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7437
  // Ignore mark word verification. If during concurrent precleaning
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7438
  // the object monitor may be locked. If during the checkpoint
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7439
  // phases, the object may already have been reached by a  different
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7440
  // path and may be at the end of the global overflow list (so
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7441
  // the mark word may be NULL).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7442
  assert(this_oop->is_oop_or_null(true/* ignore mark word */),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7443
         "expected an oop or NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7444
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7445
  // Check if oop points into the CMS generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7446
  // and is not marked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7447
  if (_span.contains(addr) && !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7448
    // a white object ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7449
    _bit_map->mark(addr);         // ... now grey
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7450
    // push on the marking stack (grey set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7451
    bool simulate_overflow = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7452
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7453
      if (CMSMarkStackOverflowALot &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7454
          _collector->simulate_overflow()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7455
        // simulate a stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7456
        simulate_overflow = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7457
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7458
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7459
    if (simulate_overflow || !_mark_stack->push(this_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7460
      if (_concurrent_precleaning) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7461
         // During precleaning we can just dirty the appropriate card
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7462
         // in the mod union table, thus ensuring that the object remains
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7463
         // in the grey set  and continue. Note that no one can be intefering
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7464
         // with us in this action of dirtying the mod union table, so
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7465
         // no locking is required.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7466
         _mod_union_table->mark(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7467
         _collector->_ser_pmc_preclean_ovflw++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7468
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7469
         // During the remark phase, we need to remember this oop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7470
         // in the overflow list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7471
         _collector->push_on_overflow_list(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7472
         _collector->_ser_pmc_remark_ovflw++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7473
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7474
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7475
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7476
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7477
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7478
Par_PushAndMarkClosure::Par_PushAndMarkClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7479
                                               MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7480
                                               ReferenceProcessor* rp,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7481
                                               CMSBitMap* bit_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7482
                                               OopTaskQueue* work_queue,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7483
                                               CMSMarkStack* revisit_stack):
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7484
  OopClosure(rp),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7485
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7486
  _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7487
  _bit_map(bit_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7488
  _work_queue(work_queue),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7489
  _revisit_stack(revisit_stack),
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  7490
  _should_remember_klasses(collector->should_unload_classes())
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7491
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7492
  assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7493
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7494
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7495
// Grey object rescan during second checkpoint phase --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7496
// the parallel version.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7497
void Par_PushAndMarkClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7498
  oop    this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7499
  // In the assert below, we ignore the mark word because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7500
  // this oop may point to an already visited object that is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7501
  // on the overflow stack (in which case the mark word has
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7502
  // been hijacked for chaining into the overflow stack --
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7503
  // if this is the last object in the overflow stack then
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7504
  // its mark word will be NULL). Because this object may
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7505
  // have been subsequently popped off the global overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7506
  // stack, and the mark word possibly restored to the prototypical
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7507
  // value, by the time we get to examined this failing assert in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7508
  // the debugger, is_oop_or_null(false) may subsequently start
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7509
  // to hold.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7510
  assert(this_oop->is_oop_or_null(true),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7511
         "expected an oop or NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7512
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7513
  // Check if oop points into the CMS generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7514
  // and is not marked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7515
  if (_span.contains(addr) && !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7516
    // a white object ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7517
    // If we manage to "claim" the object, by being the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7518
    // first thread to mark it, then we push it on our
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7519
    // marking stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7520
    if (_bit_map->par_mark(addr)) {     // ... now grey
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7521
      // push on work queue (grey set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7522
      bool simulate_overflow = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7523
      NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7524
        if (CMSMarkStackOverflowALot &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7525
            _collector->par_simulate_overflow()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7526
          // simulate a stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7527
          simulate_overflow = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7528
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7529
      )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7530
      if (simulate_overflow || !_work_queue->push(this_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7531
        _collector->par_push_on_overflow_list(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7532
        _collector->_par_pmc_remark_ovflw++; //  imprecise OK: no need to CAS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7533
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7534
    } // Else, some other thread got there first
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7535
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7536
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7537
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7538
void PushAndMarkClosure::remember_klass(Klass* k) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7539
  if (!_revisit_stack->push(oop(k))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7540
    fatal("Revisit stack overflowed in PushAndMarkClosure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7541
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7542
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7543
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7544
void Par_PushAndMarkClosure::remember_klass(Klass* k) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7545
  if (!_revisit_stack->par_push(oop(k))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7546
    fatal("Revist stack overflowed in Par_PushAndMarkClosure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7547
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7548
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7549
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7550
void CMSPrecleanRefsYieldClosure::do_yield_work() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7551
  Mutex* bml = _collector->bitMapLock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7552
  assert_lock_strong(bml);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7553
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7554
         "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7555
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7556
  bml->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7557
  ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7558
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7559
  ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7560
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7561
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7562
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7563
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7564
    _collector->incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7565
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7566
  _collector->icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7567
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7568
  // See the comment in coordinator_yield()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7569
  for (unsigned i = 0; i < CMSYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7570
                       ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7571
                       !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7572
    os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7573
    ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7574
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7575
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7576
  ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7577
  bml->lock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7578
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7579
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7580
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7581
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7582
bool CMSPrecleanRefsYieldClosure::should_return() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7583
  if (ConcurrentMarkSweepThread::should_yield()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7584
    do_yield_work();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7585
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7586
  return _collector->foregroundGCIsActive();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7587
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7588
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7589
void MarkFromDirtyCardsClosure::do_MemRegion(MemRegion mr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7590
  assert(((size_t)mr.start())%CardTableModRefBS::card_size_in_words == 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7591
         "mr should be aligned to start at a card boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7592
  // We'd like to assert:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7593
  // assert(mr.word_size()%CardTableModRefBS::card_size_in_words == 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7594
  //        "mr should be a range of cards");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7595
  // However, that would be too strong in one case -- the last
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7596
  // partition ends at _unallocated_block which, in general, can be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7597
  // an arbitrary boundary, not necessarily card aligned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7598
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7599
    _num_dirty_cards +=
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7600
         mr.word_size()/CardTableModRefBS::card_size_in_words;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7601
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7602
  _space->object_iterate_mem(mr, &_scan_cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7603
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7604
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7605
SweepClosure::SweepClosure(CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7606
                           ConcurrentMarkSweepGeneration* g,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7607
                           CMSBitMap* bitMap, bool should_yield) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7608
  _collector(collector),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7609
  _g(g),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7610
  _sp(g->cmsSpace()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7611
  _limit(_sp->sweep_limit()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7612
  _freelistLock(_sp->freelistLock()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7613
  _bitMap(bitMap),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7614
  _yield(should_yield),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7615
  _inFreeRange(false),           // No free range at beginning of sweep
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7616
  _freeRangeInFreeLists(false),  // No free range at beginning of sweep
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7617
  _lastFreeRangeCoalesced(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7618
  _freeFinger(g->used_region().start())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7619
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7620
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7621
    _numObjectsFreed = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7622
    _numWordsFreed   = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7623
    _numObjectsLive = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7624
    _numWordsLive = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7625
    _numObjectsAlreadyFree = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7626
    _numWordsAlreadyFree = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7627
    _last_fc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7628
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7629
    _sp->initializeIndexedFreeListArrayReturnedBytes();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7630
    _sp->dictionary()->initializeDictReturnedBytes();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7631
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7632
  assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7633
         "sweep _limit out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7634
  if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7635
    gclog_or_tty->print("\n====================\nStarting new sweep\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7636
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7637
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7638
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7639
// We need this destructor to reclaim any space at the end
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7640
// of the space, which do_blk below may not have added back to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7641
// the free lists. [basically dealing with the "fringe effect"]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7642
SweepClosure::~SweepClosure() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7643
  assert_lock_strong(_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7644
  // this should be treated as the end of a free run if any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7645
  // The current free range should be returned to the free lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7646
  // as one coalesced chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7647
  if (inFreeRange()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7648
    flushCurFreeChunk(freeFinger(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7649
      pointer_delta(_limit, freeFinger()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7650
    assert(freeFinger() < _limit, "the finger pointeth off base");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7651
    if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7652
      gclog_or_tty->print("destructor:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7653
      gclog_or_tty->print("Sweep:put_free_blk 0x%x ("SIZE_FORMAT") "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7654
                 "[coalesced:"SIZE_FORMAT"]\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7655
                 freeFinger(), pointer_delta(_limit, freeFinger()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7656
                 lastFreeRangeCoalesced());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7657
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7658
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7659
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7660
    if (Verbose && PrintGC) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7661
      gclog_or_tty->print("Collected "SIZE_FORMAT" objects, "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7662
                          SIZE_FORMAT " bytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7663
                 _numObjectsFreed, _numWordsFreed*sizeof(HeapWord));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7664
      gclog_or_tty->print_cr("\nLive "SIZE_FORMAT" objects,  "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7665
                             SIZE_FORMAT" bytes  "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7666
        "Already free "SIZE_FORMAT" objects, "SIZE_FORMAT" bytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7667
        _numObjectsLive, _numWordsLive*sizeof(HeapWord),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7668
        _numObjectsAlreadyFree, _numWordsAlreadyFree*sizeof(HeapWord));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7669
      size_t totalBytes = (_numWordsFreed + _numWordsLive + _numWordsAlreadyFree) *
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7670
        sizeof(HeapWord);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7671
      gclog_or_tty->print_cr("Total sweep: "SIZE_FORMAT" bytes", totalBytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7672
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7673
      if (PrintCMSStatistics && CMSVerifyReturnedBytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7674
        size_t indexListReturnedBytes = _sp->sumIndexedFreeListArrayReturnedBytes();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7675
        size_t dictReturnedBytes = _sp->dictionary()->sumDictReturnedBytes();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7676
        size_t returnedBytes = indexListReturnedBytes + dictReturnedBytes;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7677
        gclog_or_tty->print("Returned "SIZE_FORMAT" bytes", returnedBytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7678
        gclog_or_tty->print("   Indexed List Returned "SIZE_FORMAT" bytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7679
          indexListReturnedBytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7680
        gclog_or_tty->print_cr("        Dictionary Returned "SIZE_FORMAT" bytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7681
          dictReturnedBytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7682
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7683
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7684
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7685
  // Now, in debug mode, just null out the sweep_limit
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7686
  NOT_PRODUCT(_sp->clear_sweep_limit();)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7687
  if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7688
    gclog_or_tty->print("end of sweep\n================\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7689
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7690
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7691
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7692
void SweepClosure::initialize_free_range(HeapWord* freeFinger,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7693
    bool freeRangeInFreeLists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7694
  if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7695
    gclog_or_tty->print("---- Start free range 0x%x with free block [%d] (%d)\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7696
               freeFinger, _sp->block_size(freeFinger),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7697
               freeRangeInFreeLists);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7698
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7699
  assert(!inFreeRange(), "Trampling existing free range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7700
  set_inFreeRange(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7701
  set_lastFreeRangeCoalesced(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7702
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7703
  set_freeFinger(freeFinger);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7704
  set_freeRangeInFreeLists(freeRangeInFreeLists);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7705
  if (CMSTestInFreeList) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7706
    if (freeRangeInFreeLists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7707
      FreeChunk* fc = (FreeChunk*) freeFinger;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7708
      assert(fc->isFree(), "A chunk on the free list should be free.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7709
      assert(fc->size() > 0, "Free range should have a size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7710
      assert(_sp->verifyChunkInFreeLists(fc), "Chunk is not in free lists");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7711
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7712
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7713
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7714
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7715
// Note that the sweeper runs concurrently with mutators. Thus,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7716
// it is possible for direct allocation in this generation to happen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7717
// in the middle of the sweep. Note that the sweeper also coalesces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7718
// contiguous free blocks. Thus, unless the sweeper and the allocator
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7719
// synchronize appropriately freshly allocated blocks may get swept up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7720
// This is accomplished by the sweeper locking the free lists while
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7721
// it is sweeping. Thus blocks that are determined to be free are
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7722
// indeed free. There is however one additional complication:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7723
// blocks that have been allocated since the final checkpoint and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7724
// mark, will not have been marked and so would be treated as
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7725
// unreachable and swept up. To prevent this, the allocator marks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7726
// the bit map when allocating during the sweep phase. This leads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7727
// however, to a further complication -- objects may have been allocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7728
// but not yet initialized -- in the sense that the header isn't yet
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7729
// installed. The sweeper can not then determine the size of the block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7730
// in order to skip over it. To deal with this case, we use a technique
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7731
// (due to Printezis) to encode such uninitialized block sizes in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7732
// bit map. Since the bit map uses a bit per every HeapWord, but the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7733
// CMS generation has a minimum object size of 3 HeapWords, it follows
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7734
// that "normal marks" won't be adjacent in the bit map (there will
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7735
// always be at least two 0 bits between successive 1 bits). We make use
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7736
// of these "unused" bits to represent uninitialized blocks -- the bit
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7737
// corresponding to the start of the uninitialized object and the next
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7738
// bit are both set. Finally, a 1 bit marks the end of the object that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7739
// started with the two consecutive 1 bits to indicate its potentially
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7740
// uninitialized state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7741
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7742
size_t SweepClosure::do_blk_careful(HeapWord* addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7743
  FreeChunk* fc = (FreeChunk*)addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7744
  size_t res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7745
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7746
  // check if we are done sweepinrg
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7747
  if (addr == _limit) { // we have swept up to the limit, do nothing more
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7748
    assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7749
           "sweep _limit out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7750
    // help the closure application finish
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7751
    return pointer_delta(_sp->end(), _limit);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7752
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7753
  assert(addr <= _limit, "sweep invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7754
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7755
  // check if we should yield
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7756
  do_yield_check(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7757
  if (fc->isFree()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7758
    // Chunk that is already free
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7759
    res = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7760
    doAlreadyFreeChunk(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7761
    debug_only(_sp->verifyFreeLists());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7762
    assert(res == fc->size(), "Don't expect the size to change");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7763
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7764
      _numObjectsAlreadyFree++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7765
      _numWordsAlreadyFree += res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7766
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7767
    NOT_PRODUCT(_last_fc = fc;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7768
  } else if (!_bitMap->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7769
    // Chunk is fresh garbage
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7770
    res = doGarbageChunk(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7771
    debug_only(_sp->verifyFreeLists());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7772
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7773
      _numObjectsFreed++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7774
      _numWordsFreed += res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7775
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7776
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7777
    // Chunk that is alive.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7778
    res = doLiveChunk(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7779
    debug_only(_sp->verifyFreeLists());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7780
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7781
        _numObjectsLive++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7782
        _numWordsLive += res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7783
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7784
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7785
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7786
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7787
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7788
// For the smart allocation, record following
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7789
//  split deaths - a free chunk is removed from its free list because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7790
//      it is being split into two or more chunks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7791
//  split birth - a free chunk is being added to its free list because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7792
//      a larger free chunk has been split and resulted in this free chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7793
//  coal death - a free chunk is being removed from its free list because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7794
//      it is being coalesced into a large free chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7795
//  coal birth - a free chunk is being added to its free list because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7796
//      it was created when two or more free chunks where coalesced into
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7797
//      this free chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7798
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7799
// These statistics are used to determine the desired number of free
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7800
// chunks of a given size.  The desired number is chosen to be relative
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7801
// to the end of a CMS sweep.  The desired number at the end of a sweep
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7802
// is the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7803
//      count-at-end-of-previous-sweep (an amount that was enough)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7804
//              - count-at-beginning-of-current-sweep  (the excess)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7805
//              + split-births  (gains in this size during interval)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7806
//              - split-deaths  (demands on this size during interval)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7807
// where the interval is from the end of one sweep to the end of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7808
// next.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7809
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7810
// When sweeping the sweeper maintains an accumulated chunk which is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7811
// the chunk that is made up of chunks that have been coalesced.  That
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7812
// will be termed the left-hand chunk.  A new chunk of garbage that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7813
// is being considered for coalescing will be referred to as the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7814
// right-hand chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7815
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7816
// When making a decision on whether to coalesce a right-hand chunk with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7817
// the current left-hand chunk, the current count vs. the desired count
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7818
// of the left-hand chunk is considered.  Also if the right-hand chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7819
// is near the large chunk at the end of the heap (see
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7820
// ConcurrentMarkSweepGeneration::isNearLargestChunk()), then the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7821
// left-hand chunk is coalesced.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7822
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7823
// When making a decision about whether to split a chunk, the desired count
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7824
// vs. the current count of the candidate to be split is also considered.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7825
// If the candidate is underpopulated (currently fewer chunks than desired)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7826
// a chunk of an overpopulated (currently more chunks than desired) size may
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7827
// be chosen.  The "hint" associated with a free list, if non-null, points
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7828
// to a free list which may be overpopulated.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7829
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7830
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7831
void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7832
  size_t size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7833
  // Chunks that cannot be coalesced are not in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7834
  // free lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7835
  if (CMSTestInFreeList && !fc->cantCoalesce()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7836
    assert(_sp->verifyChunkInFreeLists(fc),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7837
      "free chunk should be in free lists");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7838
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7839
  // a chunk that is already free, should not have been
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7840
  // marked in the bit map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7841
  HeapWord* addr = (HeapWord*) fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7842
  assert(!_bitMap->isMarked(addr), "free chunk should be unmarked");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7843
  // Verify that the bit map has no bits marked between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7844
  // addr and purported end of this block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7845
  _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7846
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7847
  // Some chunks cannot be coalesced in under any circumstances.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7848
  // See the definition of cantCoalesce().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7849
  if (!fc->cantCoalesce()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7850
    // This chunk can potentially be coalesced.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7851
    if (_sp->adaptive_freelists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7852
      // All the work is done in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7853
      doPostIsFreeOrGarbageChunk(fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7854
    } else {  // Not adaptive free lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7855
      // this is a free chunk that can potentially be coalesced by the sweeper;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7856
      if (!inFreeRange()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7857
        // if the next chunk is a free block that can't be coalesced
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7858
        // it doesn't make sense to remove this chunk from the free lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7859
        FreeChunk* nextChunk = (FreeChunk*)(addr + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7860
        assert((HeapWord*)nextChunk <= _limit, "sweep invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7861
        if ((HeapWord*)nextChunk < _limit  &&    // there's a next chunk...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7862
            nextChunk->isFree()    &&            // which is free...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7863
            nextChunk->cantCoalesce()) {         // ... but cant be coalesced
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7864
          // nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7865
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7866
          // Potentially the start of a new free range:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7867
          // Don't eagerly remove it from the free lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7868
          // No need to remove it if it will just be put
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7869
          // back again.  (Also from a pragmatic point of view
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7870
          // if it is a free block in a region that is beyond
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7871
          // any allocated blocks, an assertion will fail)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7872
          // Remember the start of a free run.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7873
          initialize_free_range(addr, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7874
          // end - can coalesce with next chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7875
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7876
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7877
        // the midst of a free range, we are coalescing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7878
        debug_only(record_free_block_coalesced(fc);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7879
        if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7880
          gclog_or_tty->print("  -- pick up free block 0x%x (%d)\n", fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7881
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7882
        // remove it from the free lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7883
        _sp->removeFreeChunkFromFreeLists(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7884
        set_lastFreeRangeCoalesced(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7885
        // If the chunk is being coalesced and the current free range is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7886
        // in the free lists, remove the current free range so that it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7887
        // will be returned to the free lists in its entirety - all
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7888
        // the coalesced pieces included.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7889
        if (freeRangeInFreeLists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7890
          FreeChunk* ffc = (FreeChunk*) freeFinger();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7891
          assert(ffc->size() == pointer_delta(addr, freeFinger()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7892
            "Size of free range is inconsistent with chunk size.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7893
          if (CMSTestInFreeList) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7894
            assert(_sp->verifyChunkInFreeLists(ffc),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7895
              "free range is not in free lists");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7896
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7897
          _sp->removeFreeChunkFromFreeLists(ffc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7898
          set_freeRangeInFreeLists(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7899
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7900
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7901
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7902
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7903
    // Code path common to both original and adaptive free lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7904
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7905
    // cant coalesce with previous block; this should be treated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7906
    // as the end of a free run if any
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7907
    if (inFreeRange()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7908
      // we kicked some butt; time to pick up the garbage
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7909
      assert(freeFinger() < addr, "the finger pointeth off base");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7910
      flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7911
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7912
    // else, nothing to do, just continue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7913
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7914
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7915
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7916
size_t SweepClosure::doGarbageChunk(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7917
  // This is a chunk of garbage.  It is not in any free list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7918
  // Add it to a free list or let it possibly be coalesced into
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7919
  // a larger chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7920
  HeapWord* addr = (HeapWord*) fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7921
  size_t size = CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7922
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7923
  if (_sp->adaptive_freelists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7924
    // Verify that the bit map has no bits marked between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7925
    // addr and purported end of just dead object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7926
    _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7927
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7928
    doPostIsFreeOrGarbageChunk(fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7929
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7930
    if (!inFreeRange()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7931
      // start of a new free range
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7932
      assert(size > 0, "A free range should have a size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7933
      initialize_free_range(addr, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7934
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7935
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7936
      // this will be swept up when we hit the end of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7937
      // free range
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7938
      if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7939
        gclog_or_tty->print("  -- pick up garbage 0x%x (%d) \n", fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7940
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7941
      // If the chunk is being coalesced and the current free range is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7942
      // in the free lists, remove the current free range so that it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7943
      // will be returned to the free lists in its entirety - all
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7944
      // the coalesced pieces included.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7945
      if (freeRangeInFreeLists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7946
        FreeChunk* ffc = (FreeChunk*)freeFinger();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7947
        assert(ffc->size() == pointer_delta(addr, freeFinger()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7948
          "Size of free range is inconsistent with chunk size.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7949
        if (CMSTestInFreeList) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7950
          assert(_sp->verifyChunkInFreeLists(ffc),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7951
            "free range is not in free lists");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7952
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7953
        _sp->removeFreeChunkFromFreeLists(ffc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7954
        set_freeRangeInFreeLists(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7955
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7956
      set_lastFreeRangeCoalesced(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7957
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7958
    // this will be swept up when we hit the end of the free range
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7959
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7960
    // Verify that the bit map has no bits marked between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7961
    // addr and purported end of just dead object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7962
    _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7963
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7964
  return size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7965
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7966
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7967
size_t SweepClosure::doLiveChunk(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7968
  HeapWord* addr = (HeapWord*) fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7969
  // The sweeper has just found a live object. Return any accumulated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7970
  // left hand chunk to the free lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7971
  if (inFreeRange()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7972
    if (_sp->adaptive_freelists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7973
      flushCurFreeChunk(freeFinger(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7974
                        pointer_delta(addr, freeFinger()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7975
    } else { // not adaptive freelists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7976
      set_inFreeRange(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7977
      // Add the free range back to the free list if it is not already
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7978
      // there.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7979
      if (!freeRangeInFreeLists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7980
        assert(freeFinger() < addr, "the finger pointeth off base");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7981
        if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7982
          gclog_or_tty->print("Sweep:put_free_blk 0x%x (%d) "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7983
            "[coalesced:%d]\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7984
            freeFinger(), pointer_delta(addr, freeFinger()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7985
            lastFreeRangeCoalesced());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7986
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7987
        _sp->addChunkAndRepairOffsetTable(freeFinger(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7988
          pointer_delta(addr, freeFinger()), lastFreeRangeCoalesced());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7989
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7990
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7991
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7992
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7993
  // Common code path for original and adaptive free lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7994
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7995
  // this object is live: we'd normally expect this to be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7996
  // an oop, and like to assert the following:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7997
  // assert(oop(addr)->is_oop(), "live block should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7998
  // However, as we commented above, this may be an object whose
489c9b5090e2 Initial load
duke
parents:
diff changeset
  7999
  // header hasn't yet been initialized.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8000
  size_t size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8001
  assert(_bitMap->isMarked(addr), "Tautology for this control point");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8002
  if (_bitMap->isMarked(addr + 1)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8003
    // Determine the size from the bit map, rather than trying to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8004
    // compute it from the object header.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8005
    HeapWord* nextOneAddr = _bitMap->getNextMarkedWordAddress(addr + 2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8006
    size = pointer_delta(nextOneAddr + 1, addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8007
    assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8008
           "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8009
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8010
    #ifdef DEBUG
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8011
      if (oop(addr)->klass() != NULL &&
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  8012
          (   !_collector->should_unload_classes()
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8013
           || oop(addr)->is_parsable())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8014
        // Ignore mark word because we are running concurrent with mutators
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8015
        assert(oop(addr)->is_oop(true), "live block should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8016
        assert(size ==
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8017
               CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8018
               "P-mark and computed size do not agree");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8019
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8020
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8021
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8022
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8023
    // This should be an initialized object that's alive.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8024
    assert(oop(addr)->klass() != NULL &&
341
6578aad59716 6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction
ysr
parents: 182
diff changeset
  8025
           (!_collector->should_unload_classes()
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8026
            || oop(addr)->is_parsable()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8027
           "Should be an initialized object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8028
    // Ignore mark word because we are running concurrent with mutators
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8029
    assert(oop(addr)->is_oop(true), "live block should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8030
    // Verify that the bit map has no bits marked between
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8031
    // addr and purported end of this block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8032
    size = CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8033
    assert(size >= 3, "Necessary for Printezis marks to work");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8034
    assert(!_bitMap->isMarked(addr+1), "Tautology for this control point");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8035
    DEBUG_ONLY(_bitMap->verifyNoOneBitsInRange(addr+2, addr+size);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8036
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8037
  return size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8038
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8039
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8040
void SweepClosure::doPostIsFreeOrGarbageChunk(FreeChunk* fc,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8041
                                            size_t chunkSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8042
  // doPostIsFreeOrGarbageChunk() should only be called in the smart allocation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8043
  // scheme.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8044
  bool fcInFreeLists = fc->isFree();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8045
  assert(_sp->adaptive_freelists(), "Should only be used in this case.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8046
  assert((HeapWord*)fc <= _limit, "sweep invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8047
  if (CMSTestInFreeList && fcInFreeLists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8048
    assert(_sp->verifyChunkInFreeLists(fc),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8049
      "free chunk is not in free lists");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8050
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8051
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8052
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8053
  if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8054
    gclog_or_tty->print_cr("  -- pick up another chunk at 0x%x (%d)", fc, chunkSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8055
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8056
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8057
  HeapWord* addr = (HeapWord*) fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8058
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8059
  bool coalesce;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8060
  size_t left  = pointer_delta(addr, freeFinger());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8061
  size_t right = chunkSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8062
  switch (FLSCoalescePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8063
    // numeric value forms a coalition aggressiveness metric
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8064
    case 0:  { // never coalesce
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8065
      coalesce = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8066
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8067
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8068
    case 1: { // coalesce if left & right chunks on overpopulated lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8069
      coalesce = _sp->coalOverPopulated(left) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8070
                 _sp->coalOverPopulated(right);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8071
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8072
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8073
    case 2: { // coalesce if left chunk on overpopulated list (default)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8074
      coalesce = _sp->coalOverPopulated(left);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8075
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8076
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8077
    case 3: { // coalesce if left OR right chunk on overpopulated list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8078
      coalesce = _sp->coalOverPopulated(left) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8079
                 _sp->coalOverPopulated(right);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8080
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8081
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8082
    case 4: { // always coalesce
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8083
      coalesce = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8084
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8085
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8086
    default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8087
     ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8088
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8089
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8090
  // Should the current free range be coalesced?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8091
  // If the chunk is in a free range and either we decided to coalesce above
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8092
  // or the chunk is near the large block at the end of the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8093
  // (isNearLargestChunk() returns true), then coalesce this chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8094
  bool doCoalesce = inFreeRange() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8095
    (coalesce || _g->isNearLargestChunk((HeapWord*)fc));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8096
  if (doCoalesce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8097
    // Coalesce the current free range on the left with the new
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8098
    // chunk on the right.  If either is on a free list,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8099
    // it must be removed from the list and stashed in the closure.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8100
    if (freeRangeInFreeLists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8101
      FreeChunk* ffc = (FreeChunk*)freeFinger();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8102
      assert(ffc->size() == pointer_delta(addr, freeFinger()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8103
        "Size of free range is inconsistent with chunk size.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8104
      if (CMSTestInFreeList) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8105
        assert(_sp->verifyChunkInFreeLists(ffc),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8106
          "Chunk is not in free lists");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8107
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8108
      _sp->coalDeath(ffc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8109
      _sp->removeFreeChunkFromFreeLists(ffc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8110
      set_freeRangeInFreeLists(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8111
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8112
    if (fcInFreeLists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8113
      _sp->coalDeath(chunkSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8114
      assert(fc->size() == chunkSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8115
        "The chunk has the wrong size or is not in the free lists");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8116
      _sp->removeFreeChunkFromFreeLists(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8117
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8118
    set_lastFreeRangeCoalesced(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8119
  } else {  // not in a free range and/or should not coalesce
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8120
    // Return the current free range and start a new one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8121
    if (inFreeRange()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8122
      // In a free range but cannot coalesce with the right hand chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8123
      // Put the current free range into the free lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8124
      flushCurFreeChunk(freeFinger(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8125
        pointer_delta(addr, freeFinger()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8126
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8127
    // Set up for new free range.  Pass along whether the right hand
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8128
    // chunk is in the free lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8129
    initialize_free_range((HeapWord*)fc, fcInFreeLists);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8130
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8131
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8132
void SweepClosure::flushCurFreeChunk(HeapWord* chunk, size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8133
  assert(inFreeRange(), "Should only be called if currently in a free range.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8134
  assert(size > 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8135
    "A zero sized chunk cannot be added to the free lists.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8136
  if (!freeRangeInFreeLists()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8137
    if(CMSTestInFreeList) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8138
      FreeChunk* fc = (FreeChunk*) chunk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8139
      fc->setSize(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8140
      assert(!_sp->verifyChunkInFreeLists(fc),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8141
        "chunk should not be in free lists yet");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8142
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8143
    if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8144
      gclog_or_tty->print_cr(" -- add free block 0x%x (%d) to free lists",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8145
                    chunk, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8146
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8147
    // A new free range is going to be starting.  The current
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8148
    // free range has not been added to the free lists yet or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8149
    // was removed so add it back.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8150
    // If the current free range was coalesced, then the death
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8151
    // of the free range was recorded.  Record a birth now.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8152
    if (lastFreeRangeCoalesced()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8153
      _sp->coalBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8154
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8155
    _sp->addChunkAndRepairOffsetTable(chunk, size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8156
            lastFreeRangeCoalesced());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8157
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8158
  set_inFreeRange(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8159
  set_freeRangeInFreeLists(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8160
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8161
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8162
// We take a break if we've been at this for a while,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8163
// so as to avoid monopolizing the locks involved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8164
void SweepClosure::do_yield_work(HeapWord* addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8165
  // Return current free chunk being used for coalescing (if any)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8166
  // to the appropriate freelist.  After yielding, the next
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8167
  // free block encountered will start a coalescing range of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8168
  // free blocks.  If the next free block is adjacent to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8169
  // chunk just flushed, they will need to wait for the next
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8170
  // sweep to be coalesced.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8171
  if (inFreeRange()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8172
    flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8173
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8174
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8175
  // First give up the locks, then yield, then re-lock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8176
  // We should probably use a constructor/destructor idiom to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8177
  // do this unlock/lock or modify the MutexUnlocker class to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8178
  // serve our purpose. XXX
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8179
  assert_lock_strong(_bitMap->lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8180
  assert_lock_strong(_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8181
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8182
         "CMS thread should hold CMS token");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8183
  _bitMap->lock()->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8184
  _freelistLock->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8185
  ConcurrentMarkSweepThread::desynchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8186
  ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8187
  _collector->stopTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8188
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8189
  if (PrintCMSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8190
    _collector->incrementYields();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8191
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8192
  _collector->icms_wait();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8193
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8194
  // See the comment in coordinator_yield()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8195
  for (unsigned i = 0; i < CMSYieldSleepCount &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8196
                       ConcurrentMarkSweepThread::should_yield() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8197
                       !CMSCollector::foregroundGCIsActive(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8198
    os::sleep(Thread::current(), 1, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8199
    ConcurrentMarkSweepThread::acknowledge_yield_request();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8200
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8201
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8202
  ConcurrentMarkSweepThread::synchronize(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8203
  _freelistLock->lock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8204
  _bitMap->lock()->lock_without_safepoint_check();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8205
  _collector->startTimer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8206
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8207
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8208
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8209
// This is actually very useful in a product build if it can
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8210
// be called from the debugger.  Compile it into the product
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8211
// as needed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8212
bool debug_verifyChunkInFreeLists(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8213
  return debug_cms_space->verifyChunkInFreeLists(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8214
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8215
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8216
void SweepClosure::record_free_block_coalesced(FreeChunk* fc) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8217
  if (CMSTraceSweeper) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8218
    gclog_or_tty->print("Sweep:coal_free_blk 0x%x (%d)\n", fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8219
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8220
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8221
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8222
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8223
// CMSIsAliveClosure
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8224
bool CMSIsAliveClosure::do_object_b(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8225
  HeapWord* addr = (HeapWord*)obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8226
  return addr != NULL &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8227
         (!_span.contains(addr) || _bit_map->isMarked(addr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8228
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8229
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8230
// CMSKeepAliveClosure: the serial version
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8231
void CMSKeepAliveClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8232
  oop this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8233
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8234
  if (_span.contains(addr) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8235
      !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8236
    _bit_map->mark(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8237
    bool simulate_overflow = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8238
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8239
      if (CMSMarkStackOverflowALot &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8240
          _collector->simulate_overflow()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8241
        // simulate a stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8242
        simulate_overflow = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8243
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8244
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8245
    if (simulate_overflow || !_mark_stack->push(this_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8246
      _collector->push_on_overflow_list(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8247
      _collector->_ser_kac_ovflw++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8248
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8249
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8250
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8251
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8252
// CMSParKeepAliveClosure: a parallel version of the above.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8253
// The work queues are private to each closure (thread),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8254
// but (may be) available for stealing by other threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8255
void CMSParKeepAliveClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8256
  oop this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8257
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8258
  if (_span.contains(addr) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8259
      !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8260
    // In general, during recursive tracing, several threads
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8261
    // may be concurrently getting here; the first one to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8262
    // "tag" it, claims it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8263
    if (_bit_map->par_mark(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8264
      bool res = _work_queue->push(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8265
      assert(res, "Low water mark should be much less than capacity");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8266
      // Do a recursive trim in the hope that this will keep
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8267
      // stack usage lower, but leave some oops for potential stealers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8268
      trim_queue(_low_water_mark);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8269
    } // Else, another thread got there first
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8270
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8271
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8272
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8273
void CMSParKeepAliveClosure::trim_queue(uint max) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8274
  while (_work_queue->size() > max) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8275
    oop new_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8276
    if (_work_queue->pop_local(new_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8277
      assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8278
      assert(_bit_map->isMarked((HeapWord*)new_oop),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8279
             "no white objects on this stack!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8280
      assert(_span.contains((HeapWord*)new_oop), "Out of bounds oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8281
      // iterate over the oops in this oop, marking and pushing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8282
      // the ones in CMS heap (i.e. in _span).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8283
      new_oop->oop_iterate(&_mark_and_push);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8284
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8285
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8286
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8287
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8288
void CMSInnerParMarkAndPushClosure::do_oop(oop* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8289
  oop this_oop = *p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8290
  HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8291
  if (_span.contains(addr) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8292
      !_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8293
    if (_bit_map->par_mark(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8294
      bool simulate_overflow = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8295
      NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8296
        if (CMSMarkStackOverflowALot &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8297
            _collector->par_simulate_overflow()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8298
          // simulate a stack overflow
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8299
          simulate_overflow = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8300
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8301
      )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8302
      if (simulate_overflow || !_work_queue->push(this_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8303
        _collector->par_push_on_overflow_list(this_oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8304
        _collector->_par_kac_ovflw++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8305
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8306
    } // Else another thread got there already
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8307
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8308
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8309
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8310
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8311
//  CMSExpansionCause                /////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8312
//////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8313
const char* CMSExpansionCause::to_string(CMSExpansionCause::Cause cause) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8314
  switch (cause) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8315
    case _no_expansion:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8316
      return "No expansion";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8317
    case _satisfy_free_ratio:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8318
      return "Free ratio";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8319
    case _satisfy_promotion:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8320
      return "Satisfy promotion";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8321
    case _satisfy_allocation:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8322
      return "allocation";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8323
    case _allocate_par_lab:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8324
      return "Par LAB";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8325
    case _allocate_par_spooling_space:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8326
      return "Par Spooling Space";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8327
    case _adaptive_size_policy:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8328
      return "Ergonomics";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8329
    default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8330
      return "unknown";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8331
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8332
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8333
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8334
void CMSDrainMarkingStackClosure::do_void() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8335
  // the max number to take from overflow list at a time
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8336
  const size_t num = _mark_stack->capacity()/4;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8337
  while (!_mark_stack->isEmpty() ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8338
         // if stack is empty, check the overflow list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8339
         _collector->take_from_overflow_list(num, _mark_stack)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8340
    oop this_oop = _mark_stack->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8341
    HeapWord* addr = (HeapWord*)this_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8342
    assert(_span.contains(addr), "Should be within span");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8343
    assert(_bit_map->isMarked(addr), "Should be marked");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8344
    assert(this_oop->is_oop(), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8345
    this_oop->oop_iterate(_keep_alive);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8346
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8347
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8348
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8349
void CMSParDrainMarkingStackClosure::do_void() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8350
  // drain queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8351
  trim_queue(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8352
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8353
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8354
// Trim our work_queue so its length is below max at return
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8355
void CMSParDrainMarkingStackClosure::trim_queue(uint max) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8356
  while (_work_queue->size() > max) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8357
    oop new_oop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8358
    if (_work_queue->pop_local(new_oop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8359
      assert(new_oop->is_oop(), "Expected an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8360
      assert(_bit_map->isMarked((HeapWord*)new_oop),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8361
             "no white objects on this stack!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8362
      assert(_span.contains((HeapWord*)new_oop), "Out of bounds oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8363
      // iterate over the oops in this oop, marking and pushing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8364
      // the ones in CMS heap (i.e. in _span).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8365
      new_oop->oop_iterate(&_mark_and_push);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8366
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8367
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8368
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8369
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8370
////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8371
// Support for Marking Stack Overflow list handling and related code
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8372
////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8373
// Much of the following code is similar in shape and spirit to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8374
// code used in ParNewGC. We should try and share that code
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8375
// as much as possible in the future.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8376
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8377
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8378
// Debugging support for CMSStackOverflowALot
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8379
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8380
// It's OK to call this multi-threaded;  the worst thing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8381
// that can happen is that we'll get a bunch of closely
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8382
// spaced simulated oveflows, but that's OK, in fact
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8383
// probably good as it would exercise the overflow code
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8384
// under contention.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8385
bool CMSCollector::simulate_overflow() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8386
  if (_overflow_counter-- <= 0) { // just being defensive
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8387
    _overflow_counter = CMSMarkStackOverflowInterval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8388
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8389
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8390
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8391
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8392
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8393
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8394
bool CMSCollector::par_simulate_overflow() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8395
  return simulate_overflow();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8396
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8397
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8398
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8399
// Single-threaded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8400
bool CMSCollector::take_from_overflow_list(size_t num, CMSMarkStack* stack) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8401
  assert(stack->isEmpty(), "Expected precondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8402
  assert(stack->capacity() > num, "Shouldn't bite more than can chew");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8403
  size_t i = num;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8404
  oop  cur = _overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8405
  const markOop proto = markOopDesc::prototype();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8406
  NOT_PRODUCT(size_t n = 0;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8407
  for (oop next; i > 0 && cur != NULL; cur = next, i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8408
    next = oop(cur->mark());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8409
    cur->set_mark(proto);   // until proven otherwise
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8410
    assert(cur->is_oop(), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8411
    bool res = stack->push(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8412
    assert(res, "Bit off more than can chew?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8413
    NOT_PRODUCT(n++;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8414
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8415
  _overflow_list = cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8416
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8417
  assert(_num_par_pushes >= n, "Too many pops?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8418
  _num_par_pushes -=n;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8419
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8420
  return !stack->isEmpty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8421
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8422
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8423
// Multi-threaded; use CAS to break off a prefix
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8424
bool CMSCollector::par_take_from_overflow_list(size_t num,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8425
                                               OopTaskQueue* work_q) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8426
  assert(work_q->size() == 0, "That's the current policy");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8427
  assert(num < work_q->max_elems(), "Can't bite more than we can chew");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8428
  if (_overflow_list == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8429
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8430
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8431
  // Grab the entire list; we'll put back a suffix
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8432
  oop prefix = (oop)Atomic::xchg_ptr(NULL, &_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8433
  if (prefix == NULL) {  // someone grabbed it before we did ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8434
    // ... we could spin for a short while, but for now we don't
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8435
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8436
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8437
  size_t i = num;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8438
  oop cur = prefix;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8439
  for (; i > 1 && cur->mark() != NULL; cur = oop(cur->mark()), i--);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8440
  if (cur->mark() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8441
    oop suffix_head = cur->mark(); // suffix will be put back on global list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8442
    cur->set_mark(NULL);           // break off suffix
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8443
    // Find tail of suffix so we can prepend suffix to global list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8444
    for (cur = suffix_head; cur->mark() != NULL; cur = (oop)(cur->mark()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8445
    oop suffix_tail = cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8446
    assert(suffix_tail != NULL && suffix_tail->mark() == NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8447
           "Tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8448
    oop observed_overflow_list = _overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8449
    do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8450
      cur = observed_overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8451
      suffix_tail->set_mark(markOop(cur));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8452
      observed_overflow_list =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8453
        (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8454
    } while (cur != observed_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8455
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8456
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8457
  // Push the prefix elements on work_q
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8458
  assert(prefix != NULL, "control point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8459
  const markOop proto = markOopDesc::prototype();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8460
  oop next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8461
  NOT_PRODUCT(size_t n = 0;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8462
  for (cur = prefix; cur != NULL; cur = next) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8463
    next = oop(cur->mark());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8464
    cur->set_mark(proto);   // until proven otherwise
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8465
    assert(cur->is_oop(), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8466
    bool res = work_q->push(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8467
    assert(res, "Bit off more than we can chew?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8468
    NOT_PRODUCT(n++;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8469
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8470
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8471
  assert(_num_par_pushes >= n, "Too many pops?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8472
  Atomic::add_ptr(-(intptr_t)n, &_num_par_pushes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8473
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8474
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8475
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8476
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8477
// Single-threaded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8478
void CMSCollector::push_on_overflow_list(oop p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8479
  NOT_PRODUCT(_num_par_pushes++;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8480
  assert(p->is_oop(), "Not an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8481
  preserve_mark_if_necessary(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8482
  p->set_mark((markOop)_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8483
  _overflow_list = p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8484
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8485
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8486
// Multi-threaded; use CAS to prepend to overflow list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8487
void CMSCollector::par_push_on_overflow_list(oop p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8488
  NOT_PRODUCT(Atomic::inc_ptr(&_num_par_pushes);)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8489
  assert(p->is_oop(), "Not an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8490
  par_preserve_mark_if_necessary(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8491
  oop observed_overflow_list = _overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8492
  oop cur_overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8493
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8494
    cur_overflow_list = observed_overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8495
    p->set_mark(markOop(cur_overflow_list));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8496
    observed_overflow_list =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8497
      (oop) Atomic::cmpxchg_ptr(p, &_overflow_list, cur_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8498
  } while (cur_overflow_list != observed_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8499
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8500
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8501
// Single threaded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8502
// General Note on GrowableArray: pushes may silently fail
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8503
// because we are (temporarily) out of C-heap for expanding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8504
// the stack. The problem is quite ubiquitous and affects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8505
// a lot of code in the JVM. The prudent thing for GrowableArray
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8506
// to do (for now) is to exit with an error. However, that may
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8507
// be too draconian in some cases because the caller may be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8508
// able to recover without much harm. For suych cases, we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8509
// should probably introduce a "soft_push" method which returns
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8510
// an indication of success or failure with the assumption that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8511
// the caller may be able to recover from a failure; code in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8512
// the VM can then be changed, incrementally, to deal with such
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8513
// failures where possible, thus, incrementally hardening the VM
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8514
// in such low resource situations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8515
void CMSCollector::preserve_mark_work(oop p, markOop m) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8516
  int PreserveMarkStackSize = 128;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8517
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8518
  if (_preserved_oop_stack == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8519
    assert(_preserved_mark_stack == NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8520
           "bijection with preserved_oop_stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8521
    // Allocate the stacks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8522
    _preserved_oop_stack  = new (ResourceObj::C_HEAP)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8523
      GrowableArray<oop>(PreserveMarkStackSize, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8524
    _preserved_mark_stack = new (ResourceObj::C_HEAP)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8525
      GrowableArray<markOop>(PreserveMarkStackSize, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8526
    if (_preserved_oop_stack == NULL || _preserved_mark_stack == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8527
      vm_exit_out_of_memory(2* PreserveMarkStackSize * sizeof(oop) /* punt */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8528
                            "Preserved Mark/Oop Stack for CMS (C-heap)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8529
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8530
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8531
  _preserved_oop_stack->push(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8532
  _preserved_mark_stack->push(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8533
  assert(m == p->mark(), "Mark word changed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8534
  assert(_preserved_oop_stack->length() == _preserved_mark_stack->length(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8535
         "bijection");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8536
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8537
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8538
// Single threaded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8539
void CMSCollector::preserve_mark_if_necessary(oop p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8540
  markOop m = p->mark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8541
  if (m->must_be_preserved(p)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8542
    preserve_mark_work(p, m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8543
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8544
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8545
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8546
void CMSCollector::par_preserve_mark_if_necessary(oop p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8547
  markOop m = p->mark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8548
  if (m->must_be_preserved(p)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8549
    MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8550
    // Even though we read the mark word without holding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8551
    // the lock, we are assured that it will not change
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8552
    // because we "own" this oop, so no other thread can
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8553
    // be trying to push it on the overflow list; see
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8554
    // the assertion in preserve_mark_work() that checks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8555
    // that m == p->mark().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8556
    preserve_mark_work(p, m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8557
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8558
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8559
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8560
// We should be able to do this multi-threaded,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8561
// a chunk of stack being a task (this is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8562
// correct because each oop only ever appears
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8563
// once in the overflow list. However, it's
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8564
// not very easy to completely overlap this with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8565
// other operations, so will generally not be done
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8566
// until all work's been completed. Because we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8567
// expect the preserved oop stack (set) to be small,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8568
// it's probably fine to do this single-threaded.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8569
// We can explore cleverer concurrent/overlapped/parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8570
// processing of preserved marks if we feel the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8571
// need for this in the future. Stack overflow should
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8572
// be so rare in practice and, when it happens, its
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8573
// effect on performance so great that this will
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8574
// likely just be in the noise anyway.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8575
void CMSCollector::restore_preserved_marks_if_any() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8576
  if (_preserved_oop_stack == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8577
    assert(_preserved_mark_stack == NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8578
           "bijection with preserved_oop_stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8579
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8580
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8581
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8582
  assert(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8583
         "world should be stopped");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8584
  assert(Thread::current()->is_ConcurrentGC_thread() ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8585
         Thread::current()->is_VM_thread(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8586
         "should be single-threaded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8587
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8588
  int length = _preserved_oop_stack->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8589
  assert(_preserved_mark_stack->length() == length, "bijection");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8590
  for (int i = 0; i < length; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8591
    oop p = _preserved_oop_stack->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8592
    assert(p->is_oop(), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8593
    assert(_span.contains(p), "oop should be in _span");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8594
    assert(p->mark() == markOopDesc::prototype(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8595
           "Set when taken from overflow list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8596
    markOop m = _preserved_mark_stack->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8597
    p->set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8598
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8599
  _preserved_mark_stack->clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8600
  _preserved_oop_stack->clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8601
  assert(_preserved_mark_stack->is_empty() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8602
         _preserved_oop_stack->is_empty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8603
         "stacks were cleared above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8604
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8605
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8606
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8607
bool CMSCollector::no_preserved_marks() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8608
  return (   (   _preserved_mark_stack == NULL
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8609
              && _preserved_oop_stack == NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8610
          || (   _preserved_mark_stack->is_empty()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8611
              && _preserved_oop_stack->is_empty()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8612
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8613
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8614
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8615
CMSAdaptiveSizePolicy* ASConcurrentMarkSweepGeneration::cms_size_policy() const
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8616
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8617
  GenCollectedHeap* gch = (GenCollectedHeap*) GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8618
  CMSAdaptiveSizePolicy* size_policy =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8619
    (CMSAdaptiveSizePolicy*) gch->gen_policy()->size_policy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8620
  assert(size_policy->is_gc_cms_adaptive_size_policy(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8621
    "Wrong type for size policy");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8622
  return size_policy;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8623
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8624
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8625
void ASConcurrentMarkSweepGeneration::resize(size_t cur_promo_size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8626
                                           size_t desired_promo_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8627
  if (cur_promo_size < desired_promo_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8628
    size_t expand_bytes = desired_promo_size - cur_promo_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8629
    if (PrintAdaptiveSizePolicy && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8630
      gclog_or_tty->print_cr(" ASConcurrentMarkSweepGeneration::resize "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8631
        "Expanding tenured generation by " SIZE_FORMAT " (bytes)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8632
        expand_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8633
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8634
    expand(expand_bytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8635
           MinHeapDeltaBytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8636
           CMSExpansionCause::_adaptive_size_policy);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8637
  } else if (desired_promo_size < cur_promo_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8638
    size_t shrink_bytes = cur_promo_size - desired_promo_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8639
    if (PrintAdaptiveSizePolicy && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8640
      gclog_or_tty->print_cr(" ASConcurrentMarkSweepGeneration::resize "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8641
        "Shrinking tenured generation by " SIZE_FORMAT " (bytes)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8642
        shrink_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8643
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8644
    shrink(shrink_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8645
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8646
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8647
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8648
CMSGCAdaptivePolicyCounters* ASConcurrentMarkSweepGeneration::gc_adaptive_policy_counters() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8649
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8650
  CMSGCAdaptivePolicyCounters* counters =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8651
    (CMSGCAdaptivePolicyCounters*) gch->collector_policy()->counters();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8652
  assert(counters->kind() == GCPolicyCounters::CMSGCAdaptivePolicyCountersKind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8653
    "Wrong kind of counters");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8654
  return counters;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8655
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8656
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8657
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8658
void ASConcurrentMarkSweepGeneration::update_counters() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8659
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8660
    _space_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8661
    _gen_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8662
    CMSGCAdaptivePolicyCounters* counters = gc_adaptive_policy_counters();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8663
    GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8664
    CMSGCStats* gc_stats_l = (CMSGCStats*) gc_stats();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8665
    assert(gc_stats_l->kind() == GCStats::CMSGCStatsKind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8666
      "Wrong gc statistics type");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8667
    counters->update_counters(gc_stats_l);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8668
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8669
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8670
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8671
void ASConcurrentMarkSweepGeneration::update_counters(size_t used) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8672
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8673
    _space_counters->update_used(used);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8674
    _space_counters->update_capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8675
    _gen_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8676
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8677
    CMSGCAdaptivePolicyCounters* counters = gc_adaptive_policy_counters();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8678
    GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8679
    CMSGCStats* gc_stats_l = (CMSGCStats*) gc_stats();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8680
    assert(gc_stats_l->kind() == GCStats::CMSGCStatsKind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8681
      "Wrong gc statistics type");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8682
    counters->update_counters(gc_stats_l);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8683
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8684
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8685
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8686
// The desired expansion delta is computed so that:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8687
// . desired free percentage or greater is used
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8688
void ASConcurrentMarkSweepGeneration::compute_new_size() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8689
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8690
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8691
  GenCollectedHeap* gch = (GenCollectedHeap*) GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8692
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8693
  // If incremental collection failed, we just want to expand
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8694
  // to the limit.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8695
  if (incremental_collection_failed()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8696
    clear_incremental_collection_failed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8697
    grow_to_reserved();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8698
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8699
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8700
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8701
  assert(UseAdaptiveSizePolicy, "Should be using adaptive sizing");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8702
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8703
  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8704
    "Wrong type of heap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8705
  int prev_level = level() - 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8706
  assert(prev_level >= 0, "The cms generation is the lowest generation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8707
  Generation* prev_gen = gch->get_gen(prev_level);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8708
  assert(prev_gen->kind() == Generation::ASParNew,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8709
    "Wrong type of young generation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8710
  ParNewGeneration* younger_gen = (ParNewGeneration*) prev_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8711
  size_t cur_eden = younger_gen->eden()->capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8712
  CMSAdaptiveSizePolicy* size_policy = cms_size_policy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8713
  size_t cur_promo = free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8714
  size_policy->compute_tenured_generation_free_space(cur_promo,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8715
                                                       max_available(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8716
                                                       cur_eden);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8717
  resize(cur_promo, size_policy->promo_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8718
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8719
  // Record the new size of the space in the cms generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8720
  // that is available for promotions.  This is temporary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8721
  // It should be the desired promo size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8722
  size_policy->avg_cms_promo()->sample(free());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8723
  size_policy->avg_old_live()->sample(used());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8724
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8725
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8726
    CMSGCAdaptivePolicyCounters* counters = gc_adaptive_policy_counters();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8727
    counters->update_cms_capacity_counter(capacity());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8728
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8729
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8730
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8731
void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8732
  assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8733
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8734
  HeapWord* old_end = _cmsSpace->end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8735
  HeapWord* unallocated_start = _cmsSpace->unallocated_block();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8736
  assert(old_end >= unallocated_start, "Miscalculation of unallocated_start");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8737
  FreeChunk* chunk_at_end = find_chunk_at_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8738
  if (chunk_at_end == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8739
    // No room to shrink
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8740
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8741
      gclog_or_tty->print_cr("No room to shrink: old_end  "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8742
        PTR_FORMAT "  unallocated_start  " PTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8743
        " chunk_at_end  " PTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8744
        old_end, unallocated_start, chunk_at_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8745
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8746
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8747
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8748
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8749
    // Find the chunk at the end of the space and determine
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8750
    // how much it can be shrunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8751
    size_t shrinkable_size_in_bytes = chunk_at_end->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8752
    size_t aligned_shrinkable_size_in_bytes =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8753
      align_size_down(shrinkable_size_in_bytes, os::vm_page_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8754
    assert(unallocated_start <= chunk_at_end->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8755
      "Inconsistent chunk at end of space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8756
    size_t bytes = MIN2(desired_bytes, aligned_shrinkable_size_in_bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8757
    size_t word_size_before = heap_word_size(_virtual_space.committed_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8758
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8759
    // Shrink the underlying space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8760
    _virtual_space.shrink_by(bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8761
    if (PrintGCDetails && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8762
      gclog_or_tty->print_cr("ConcurrentMarkSweepGeneration::shrink_by:"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8763
        " desired_bytes " SIZE_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8764
        " shrinkable_size_in_bytes " SIZE_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8765
        " aligned_shrinkable_size_in_bytes " SIZE_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8766
        "  bytes  " SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8767
        desired_bytes, shrinkable_size_in_bytes,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8768
        aligned_shrinkable_size_in_bytes, bytes);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8769
      gclog_or_tty->print_cr("          old_end  " SIZE_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8770
        "  unallocated_start  " SIZE_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8771
        old_end, unallocated_start);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8772
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8773
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8774
    // If the space did shrink (shrinking is not guaranteed),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8775
    // shrink the chunk at the end by the appropriate amount.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8776
    if (((HeapWord*)_virtual_space.high()) < old_end) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8777
      size_t new_word_size =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8778
        heap_word_size(_virtual_space.committed_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8779
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8780
      // Have to remove the chunk from the dictionary because it is changing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8781
      // size and might be someplace elsewhere in the dictionary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8782
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8783
      // Get the chunk at end, shrink it, and put it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8784
      // back.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8785
      _cmsSpace->removeChunkFromDictionary(chunk_at_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8786
      size_t word_size_change = word_size_before - new_word_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8787
      size_t chunk_at_end_old_size = chunk_at_end->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8788
      assert(chunk_at_end_old_size >= word_size_change,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8789
        "Shrink is too large");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8790
      chunk_at_end->setSize(chunk_at_end_old_size -
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8791
                          word_size_change);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8792
      _cmsSpace->freed((HeapWord*) chunk_at_end->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8793
        word_size_change);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8794
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8795
      _cmsSpace->returnChunkToDictionary(chunk_at_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8796
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8797
      MemRegion mr(_cmsSpace->bottom(), new_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8798
      _bts->resize(new_word_size);  // resize the block offset shared array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8799
      Universe::heap()->barrier_set()->resize_covered_region(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8800
      _cmsSpace->assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8801
      _cmsSpace->set_end((HeapWord*)_virtual_space.high());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8802
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8803
      NOT_PRODUCT(_cmsSpace->dictionary()->verify());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8804
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8805
      // update the space and generation capacity counters
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8806
      if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8807
        _space_counters->update_capacity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8808
        _gen_counters->update_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8809
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8810
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8811
      if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8812
        size_t new_mem_size = _virtual_space.committed_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8813
        size_t old_mem_size = new_mem_size + bytes;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8814
        gclog_or_tty->print_cr("Shrinking %s from %ldK by %ldK to %ldK",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8815
                      name(), old_mem_size/K, bytes/K, new_mem_size/K);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8816
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8817
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8818
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8819
    assert(_cmsSpace->unallocated_block() <= _cmsSpace->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8820
      "Inconsistency at end of space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8821
    assert(chunk_at_end->end() == _cmsSpace->end(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8822
      "Shrinking is inconsistent");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8823
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8824
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8825
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8826
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8827
// Transfer some number of overflown objects to usual marking
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8828
// stack. Return true if some objects were transferred.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8829
bool MarkRefsIntoAndScanClosure::take_from_overflow_list() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8830
  size_t num = MIN2((size_t)_mark_stack->capacity()/4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8831
                    (size_t)ParGCDesiredObjsFromOverflowList);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8832
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8833
  bool res = _collector->take_from_overflow_list(num, _mark_stack);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8834
  assert(_collector->overflow_list_is_empty() || res,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8835
         "If list is not empty, we should have taken something");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8836
  assert(!res || !_mark_stack->isEmpty(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8837
         "If we took something, it should now be on our stack");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8838
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8839
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8840
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8841
size_t MarkDeadObjectsClosure::do_blk(HeapWord* addr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8842
  size_t res = _sp->block_size_no_stall(addr, _collector);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8843
  assert(res != 0, "Should always be able to compute a size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8844
  if (_sp->block_is_obj(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8845
    if (_live_bit_map->isMarked(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8846
      // It can't have been dead in a previous cycle
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8847
      guarantee(!_dead_bit_map->isMarked(addr), "No resurrection!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8848
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8849
      _dead_bit_map->mark(addr);      // mark the dead object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8850
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8851
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8852
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  8853
}