hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
author ysr
Thu, 20 Nov 2008 16:56:09 -0800
changeset 1606 dcf9714addbe
parent 977 b90650e2a9f7
child 1607 be7d05bc07b2
permissions -rw-r--r--
6684579: SoftReference processing can be made more efficient Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not. Reviewed-by: jmasa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
670
ddf3e9583f2f 6719955: Update copyright year
xdono
parents: 593
diff changeset
     2
 * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
# include "incls/_precompiled.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
# include "incls/_parNewGeneration.cpp.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
#ifdef _MSC_VER
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
#pragma warning( push )
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
ParScanThreadState::ParScanThreadState(Space* to_space_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
                                       ParNewGeneration* gen_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
                                       Generation* old_gen_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
                                       int thread_num_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
                                       ObjToScanQueueSet* work_queue_set_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
                                       size_t desired_plab_sz_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
                                       ParallelTaskTerminator& term_) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
  _to_space(to_space_), _old_gen(old_gen_), _thread_num(thread_num_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
  _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
  _ageTable(false), // false ==> not the global age table, no perf data.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
  _to_space_alloc_buffer(desired_plab_sz_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
  _to_space_closure(gen_, this), _old_gen_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
  _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
  _older_gen_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  _evacuate_followers(this, &_to_space_closure, &_old_gen_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
                      &_to_space_root_closure, gen_, &_old_gen_root_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
                      work_queue_set_, &term_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
  _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
  _keep_alive_closure(&_scan_weak_ref_closure),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
  _pushes(0), _pops(0), _steals(0), _steal_attempts(0), _term_attempts(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
  _strong_roots_time(0.0), _term_time(0.0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  _survivor_chunk_array =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
    (ChunkArray*) old_gen()->get_data_recorder(thread_num());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
  _hash_seed = 17;  // Might want to take time-based random value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
  _start = os::elapsedTime();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
  _old_gen_closure.set_generation(old_gen_);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
  _old_gen_root_closure.set_generation(old_gen_);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
#ifdef _MSC_VER
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
#pragma warning( pop )
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
void ParScanThreadState::record_survivor_plab(HeapWord* plab_start,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
                                              size_t plab_word_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
  ChunkArray* sca = survivor_chunk_array();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  if (sca != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
    // A non-null SCA implies that we want the PLAB data recorded.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
    sca->record_sample(plab_start, plab_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
bool ParScanThreadState::should_be_partially_scanned(oop new_obj, oop old_obj) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  return new_obj->is_objArray() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
         arrayOop(new_obj)->length() > ParGCArrayScanChunk &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
         new_obj != old_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
void ParScanThreadState::scan_partial_array_and_push_remainder(oop old) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
  assert(old->is_objArray(), "must be obj array");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
  assert(old->is_forwarded(), "must be forwarded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  assert(Universe::heap()->is_in_reserved(old), "must be in heap.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  assert(!_old_gen->is_in(old), "must be in young generation.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
  objArrayOop obj = objArrayOop(old->forwardee());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
  // Process ParGCArrayScanChunk elements now
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  // and push the remainder back onto queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
  int start     = arrayOop(old)->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
  int end       = obj->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
  int remainder = end - start;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  assert(start <= end, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
  if (remainder > 2 * ParGCArrayScanChunk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
    // Test above combines last partial chunk with a full chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
    end = start + ParGCArrayScanChunk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
    arrayOop(old)->set_length(end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
    // Push remainder.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
    bool ok = work_queue()->push(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
    assert(ok, "just popped, push must be okay");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
    note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
    // Restore length so that it can be used if there
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    // is a promotion failure and forwarding pointers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
    // must be removed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
    arrayOop(old)->set_length(end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
  }
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   107
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
  // process our set of indices (include header in first chunk)
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   109
  // should make sure end is even (aligned to HeapWord in case of compressed oops)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
  if ((HeapWord *)obj < young_old_boundary()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
    // object is in to_space
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   112
    obj->oop_iterate_range(&_to_space_closure, start, end);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
    // object is in old generation
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   115
    obj->oop_iterate_range(&_old_gen_closure, start, end);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
void ParScanThreadState::trim_queues(int max_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
  ObjToScanQueue* queue = work_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
  while (queue->size() > (juint)max_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
    oop obj_to_scan;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
    if (queue->pop_local(obj_to_scan)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
      note_pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
      if ((HeapWord *)obj_to_scan < young_old_boundary()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
        if (obj_to_scan->is_objArray() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
            obj_to_scan->is_forwarded() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
            obj_to_scan->forwardee() != obj_to_scan) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
          scan_partial_array_and_push_remainder(obj_to_scan);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
          // object is in to_space
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
          obj_to_scan->oop_iterate(&_to_space_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
        // object is in old generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
        obj_to_scan->oop_iterate(&_old_gen_closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
  // Otherwise, if the object is small enough, try to reallocate the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
  // buffer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  HeapWord* obj = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  if (!_to_space_full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
    ParGCAllocBuffer* const plab = to_space_alloc_buffer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
    Space*            const sp   = to_space();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
    if (word_sz * 100 <
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
        ParallelGCBufferWastePct * plab->word_sz()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
      // Is small enough; abandon this buffer and start a new one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
      plab->retire(false, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
      size_t buf_size = plab->word_sz();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
      HeapWord* buf_space = sp->par_allocate(buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
      if (buf_space == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
        const size_t min_bytes =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
          ParGCAllocBuffer::min_size() << LogHeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
        size_t free_bytes = sp->free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
        while(buf_space == NULL && free_bytes >= min_bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
          buf_size = free_bytes >> LogHeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
          assert(buf_size == (size_t)align_object_size(buf_size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
                 "Invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
          buf_space  = sp->par_allocate(buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
          free_bytes = sp->free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
      if (buf_space != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
        plab->set_word_size(buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
        plab->set_buf(buf_space);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
        record_survivor_plab(buf_space, buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
        obj = plab->allocate(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
        // Note that we cannot compare buf_size < word_sz below
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
        // because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
        assert(obj != NULL || plab->words_remaining() < word_sz,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
               "Else should have been able to allocate");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
        // It's conceivable that we may be able to use the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
        // buffer we just grabbed for subsequent small requests
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
        // even if not for this one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
        // We're used up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
        _to_space_full = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
      // Too large; allocate the object individually.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
      obj = sp->par_allocate(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  return obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
                                                size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  // Is the alloc in the current alloc buffer?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  if (to_space_alloc_buffer()->contains(obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
    assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
           "Should contain whole object.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
    to_space_alloc_buffer()->undo_allocation(obj, word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
    SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
class ParScanThreadStateSet: private ResourceArray {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  // Initializes states for the specified number of threads;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
  ParScanThreadStateSet(int                     num_threads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
                        Space&                  to_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
                        ParNewGeneration&       gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
                        Generation&             old_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
                        ObjToScanQueueSet&      queue_set,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
                        size_t                  desired_plab_sz,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
                        ParallelTaskTerminator& term);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
  inline ParScanThreadState& thread_sate(int i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
  int pushes() { return _pushes; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
  int pops()   { return _pops; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
  int steals() { return _steals; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
  void reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
  void flush();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  ParallelTaskTerminator& _term;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  ParNewGeneration&       _gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
  Generation&             _next_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
  // staticstics
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
  int _pushes;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
  int _pops;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
  int _steals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
ParScanThreadStateSet::ParScanThreadStateSet(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  int num_threads, Space& to_space, ParNewGeneration& gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  Generation& old_gen, ObjToScanQueueSet& queue_set,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
  size_t desired_plab_sz, ParallelTaskTerminator& term)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
  : ResourceArray(sizeof(ParScanThreadState), num_threads),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
    _gen(gen), _next_gen(old_gen), _term(term),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
    _pushes(0), _pops(0), _steals(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  assert(num_threads > 0, "sanity check!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
  // Initialize states.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
  for (int i = 0; i < num_threads; ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
    new ((ParScanThreadState*)_data + i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
        ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
                           desired_plab_sz, term);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
inline ParScanThreadState& ParScanThreadStateSet::thread_sate(int i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
  assert(i >= 0 && i < length(), "sanity check!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
  return ((ParScanThreadState*)_data)[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
void ParScanThreadStateSet::reset()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
  _term.reset_for_reuse();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
void ParScanThreadStateSet::flush()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
  for (int i = 0; i < length(); ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
    ParScanThreadState& par_scan_state = thread_sate(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
    // Flush stats related to To-space PLAB activity and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
    // retire the last buffer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
    par_scan_state.to_space_alloc_buffer()->
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
      flush_stats_and_retire(_gen.plab_stats(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
                             false /* !retain */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
    // Every thread has its own age table.  We need to merge
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
    // them all into one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
    ageTable *local_table = par_scan_state.age_table();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    _gen.age_table()->merge(local_table);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
    // Inform old gen that we're done.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
    _next_gen.par_promote_alloc_done(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
    _next_gen.par_oop_since_save_marks_iterate_done(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
    // Flush stats related to work queue activity (push/pop/steal)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
    // This could conceivably become a bottleneck; if so, we'll put the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
    // stat's gathering under the flag.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
    if (PAR_STATS_ENABLED) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
      _pushes += par_scan_state.pushes();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
      _pops   += par_scan_state.pops();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
      _steals += par_scan_state.steals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
      if (ParallelGCVerbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
        gclog_or_tty->print("Thread %d complete:\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
                            "  Pushes: %7d    Pops: %7d    Steals %7d (in %d attempts)\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
                            i, par_scan_state.pushes(), par_scan_state.pops(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
                            par_scan_state.steals(), par_scan_state.steal_attempts());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
        if (par_scan_state.overflow_pushes() > 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
            par_scan_state.overflow_refills() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
          gclog_or_tty->print("  Overflow pushes: %7d    "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
                              "Overflow refills: %7d for %d objs.\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
                              par_scan_state.overflow_pushes(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
                              par_scan_state.overflow_refills(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
                              par_scan_state.overflow_refill_objs());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
        double elapsed = par_scan_state.elapsed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
        double strong_roots = par_scan_state.strong_roots_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
        double term = par_scan_state.term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
        gclog_or_tty->print(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
                            "  Elapsed: %7.2f ms.\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
                            "    Strong roots: %7.2f ms (%6.2f%%)\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
                            "    Termination:  %7.2f ms (%6.2f%%) (in %d entries)\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
                           elapsed * 1000.0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
                           strong_roots * 1000.0, (strong_roots*100.0/elapsed),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
                           term * 1000.0, (term*100.0/elapsed),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
                           par_scan_state.term_attempts());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
ParScanClosure::ParScanClosure(ParNewGeneration* g,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
                               ParScanThreadState* par_scan_state) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
  OopsInGenClosure(g), _par_scan_state(par_scan_state), _g(g)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
  assert(_g->level() == 0, "Optimized for youngest generation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
  _boundary = _g->reserved().end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   329
void ParScanWithBarrierClosure::do_oop(oop* p)       { ParScanClosure::do_oop_work(p, true, false); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   330
void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   331
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   332
void ParScanWithoutBarrierClosure::do_oop(oop* p)       { ParScanClosure::do_oop_work(p, false, false); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   333
void ParScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, false); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   334
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   335
void ParRootScanWithBarrierTwoGensClosure::do_oop(oop* p)       { ParScanClosure::do_oop_work(p, true, true); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   336
void ParRootScanWithBarrierTwoGensClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, true); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   337
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   338
void ParRootScanWithoutBarrierClosure::do_oop(oop* p)       { ParScanClosure::do_oop_work(p, false, true); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   339
void ParRootScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, true); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   340
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
ParScanWeakRefClosure::ParScanWeakRefClosure(ParNewGeneration* g,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
                                             ParScanThreadState* par_scan_state)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
  : ScanWeakRefClosure(g), _par_scan_state(par_scan_state)
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   344
{}
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   345
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   346
void ParScanWeakRefClosure::do_oop(oop* p)       { ParScanWeakRefClosure::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   347
void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
#ifdef WIN32
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
#pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
ParEvacuateFollowersClosure::ParEvacuateFollowersClosure(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
    ParScanThreadState* par_scan_state_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
    ParScanWithoutBarrierClosure* to_space_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
    ParScanWithBarrierClosure* old_gen_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
    ParRootScanWithoutBarrierClosure* to_space_root_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
    ParNewGeneration* par_gen_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
    ParRootScanWithBarrierTwoGensClosure* old_gen_root_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
    ObjToScanQueueSet* task_queues_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
    ParallelTaskTerminator* terminator_) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
    _par_scan_state(par_scan_state_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
    _to_space_closure(to_space_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
    _old_gen_closure(old_gen_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
    _to_space_root_closure(to_space_root_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
    _old_gen_root_closure(old_gen_root_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
    _par_gen(par_gen_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
    _task_queues(task_queues_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
    _terminator(terminator_)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
{}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
void ParEvacuateFollowersClosure::do_void() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  ObjToScanQueue* work_q = par_scan_state()->work_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
    // Scan to-space and old-gen objs until we run out of both.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
    oop obj_to_scan;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
    par_scan_state()->trim_queues(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
    // We have no local work, attempt to steal from other threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
    // attempt to steal work from promoted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
    par_scan_state()->note_steal_attempt();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
    if (task_queues()->steal(par_scan_state()->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
                             par_scan_state()->hash_seed(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
                             obj_to_scan)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
      par_scan_state()->note_steal();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
      bool res = work_q->push(obj_to_scan);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
      assert(res, "Empty queue should have room for a push.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
      par_scan_state()->note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
      //   if successful, goto Start.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
      // try global overflow list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
    } else if (par_gen()->take_from_overflow_list(par_scan_state())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
    // Otherwise, offer termination.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
    par_scan_state()->start_term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
    if (terminator()->offer_termination()) break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
    par_scan_state()->end_term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
  // Finish the last termination pause.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
  par_scan_state()->end_term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* next_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
                HeapWord* young_old_boundary, ParScanThreadStateSet* state_set) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
    AbstractGangTask("ParNewGeneration collection"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
    _gen(gen), _next_gen(next_gen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
    _young_old_boundary(young_old_boundary),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
    _state_set(state_set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
  {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
void ParNewGenTask::work(int i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
  // Since this is being done in a separate thread, need new resource
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
  // and handle marks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
  HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
  // We would need multiple old-gen queues otherwise.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
  guarantee(gch->n_gens() == 2,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
     "Par young collection currently only works with one older gen.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
  Generation* old_gen = gch->next_gen(_gen);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
  ParScanThreadState& par_scan_state = _state_set->thread_sate(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
  par_scan_state.set_young_old_boundary(_young_old_boundary);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
  par_scan_state.start_strong_roots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
  gch->gen_process_strong_roots(_gen->level(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
                                true, // Process younger gens, if any,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
                                      // as strong roots.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
                                false,// not collecting perm generation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
                                SharedHeap::SO_AllClasses,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
                                &par_scan_state.older_gen_closure(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
                                &par_scan_state.to_space_root_closure());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
  par_scan_state.end_strong_roots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
  // "evacuate followers".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
  par_scan_state.evacuate_followers_closure().do_void();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
#ifdef _MSC_VER
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
#pragma warning( push )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
ParNewGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
  : DefNewGeneration(rs, initial_byte_size, level, "PCopy"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
  _overflow_list(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
  _is_alive_closure(this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
  _plab_stats(YoungPLABSize, PLABWeight)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
  _task_queues = new ObjToScanQueueSet(ParallelGCThreads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
  guarantee(_task_queues != NULL, "task_queues allocation failure.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
  for (uint i1 = 0; i1 < ParallelGCThreads; i1++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
    ObjToScanQueuePadded *q_padded = new ObjToScanQueuePadded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
    guarantee(q_padded != NULL, "work_queue Allocation failure.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
    _task_queues->register_queue(i1, &q_padded->work_queue);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
  for (uint i2 = 0; i2 < ParallelGCThreads; i2++)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
    _task_queues->queue(i2)->initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
    EXCEPTION_MARK;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
    ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
    const char* cname =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
         PerfDataManager::counter_name(_gen_counters->name_space(), "threads");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
                                     ParallelGCThreads, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
#ifdef _MSC_VER
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
#pragma warning( pop )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
// ParNewGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
ParKeepAliveClosure::ParKeepAliveClosure(ParScanWeakRefClosure* cl) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
  DefNewGeneration::KeepAliveClosure(cl), _par_cl(cl) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   490
template <class T>
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   491
void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop_work(T* p) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   492
#ifdef ASSERT
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   493
  {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   494
    assert(!oopDesc::is_null(*p), "expected non-null ref");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   495
    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   496
    // We never expect to see a null reference being processed
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   497
    // as a weak reference.
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   498
    assert(obj->is_oop(), "expected an oop while scanning weak refs");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   499
  }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   500
#endif // ASSERT
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
  _par_cl->do_oop_nv(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
  if (Universe::heap()->is_in_reserved(p)) {
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   505
    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   506
    _rs->write_ref_field_gc_par(p, obj);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   510
void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(oop* p)       { ParKeepAliveClosure::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   511
void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(narrowOop* p) { ParKeepAliveClosure::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   512
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
// ParNewGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
KeepAliveClosure::KeepAliveClosure(ScanWeakRefClosure* cl) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
  DefNewGeneration::KeepAliveClosure(cl) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   517
template <class T>
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   518
void /*ParNewGeneration::*/KeepAliveClosure::do_oop_work(T* p) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   519
#ifdef ASSERT
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   520
  {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   521
    assert(!oopDesc::is_null(*p), "expected non-null ref");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   522
    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   523
    // We never expect to see a null reference being processed
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   524
    // as a weak reference.
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   525
    assert(obj->is_oop(), "expected an oop while scanning weak refs");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   526
  }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   527
#endif // ASSERT
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
  _cl->do_oop_nv(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  if (Universe::heap()->is_in_reserved(p)) {
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   532
    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   533
    _rs->write_ref_field_gc_par(p, obj);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   537
void /*ParNewGeneration::*/KeepAliveClosure::do_oop(oop* p)       { KeepAliveClosure::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   538
void /*ParNewGeneration::*/KeepAliveClosure::do_oop(narrowOop* p) { KeepAliveClosure::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   539
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   540
template <class T> void ScanClosureWithParBarrier::do_oop_work(T* p) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   541
  T heap_oop = oopDesc::load_heap_oop(p);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   542
  if (!oopDesc::is_null(heap_oop)) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   543
    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
    if ((HeapWord*)obj < _boundary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
      assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?");
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   546
      oop new_obj = obj->is_forwarded()
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   547
                      ? obj->forwardee()
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   548
                      : _g->DefNewGeneration::copy_to_survivor_space(obj);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   549
      oopDesc::encode_store_heap_oop_not_null(p, new_obj);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
    if (_gc_barrier) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
      // If p points to a younger generation, mark the card.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
      if ((HeapWord*)obj < _gen_boundary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
        _rs->write_ref_field_gc_par(p, obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   560
void ScanClosureWithParBarrier::do_oop(oop* p)       { ScanClosureWithParBarrier::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   561
void ScanClosureWithParBarrier::do_oop(narrowOop* p) { ScanClosureWithParBarrier::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   562
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
class ParNewRefProcTaskProxy: public AbstractGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
  typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
  ParNewRefProcTaskProxy(ProcessTask& task, ParNewGeneration& gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
                         Generation& next_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
                         HeapWord* young_old_boundary,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
                         ParScanThreadStateSet& state_set);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
  virtual void work(int i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
  ParNewGeneration&      _gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
  ProcessTask&           _task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
  Generation&            _next_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
  HeapWord*              _young_old_boundary;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
  ParScanThreadStateSet& _state_set;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
ParNewRefProcTaskProxy::ParNewRefProcTaskProxy(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
    ProcessTask& task, ParNewGeneration& gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
    Generation& next_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
    HeapWord* young_old_boundary,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
    ParScanThreadStateSet& state_set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
  : AbstractGangTask("ParNewGeneration parallel reference processing"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
    _gen(gen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
    _task(task),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
    _next_gen(next_gen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
    _young_old_boundary(young_old_boundary),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
    _state_set(state_set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
void ParNewRefProcTaskProxy::work(int i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
  HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
  ParScanThreadState& par_scan_state = _state_set.thread_sate(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
  par_scan_state.set_young_old_boundary(_young_old_boundary);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
  _task.work(i, par_scan_state.is_alive_closure(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
             par_scan_state.keep_alive_closure(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
             par_scan_state.evacuate_followers_closure());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
class ParNewRefEnqueueTaskProxy: public AbstractGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
  typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
  EnqueueTask& _task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
  ParNewRefEnqueueTaskProxy(EnqueueTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
    : AbstractGangTask("ParNewGeneration parallel reference enqueue"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
      _task(task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
  { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
  virtual void work(int i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
    _task.work(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
void ParNewRefProcTaskExecutor::execute(ProcessTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
         "not a generational heap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
  ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
                                 _generation.reserved().end(), _state_set);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
  workers->run_task(&rp_task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
  _state_set.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
  ParNewRefEnqueueTaskProxy enq_task(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
  workers->run_task(&enq_task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
void ParNewRefProcTaskExecutor::set_single_threaded_mode()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
  _state_set.flush();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
  gch->set_par_threads(0);  // 0 ==> non-parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
  gch->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
ScanClosureWithParBarrier::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
  ScanClosure(g, gc_barrier) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
EvacuateFollowersClosureGeneral::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
                                OopsInGenClosure* cur,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
                                OopsInGenClosure* older) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
  _gch(gch), _level(level),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
  _scan_cur_or_nonheap(cur), _scan_older(older)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
{}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
void EvacuateFollowersClosureGeneral::do_void() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
    // Beware: this call will lead to closure applications via virtual
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
    // calls.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
    _gch->oop_since_save_marks_iterate(_level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
                                       _scan_cur_or_nonheap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
                                       _scan_older);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
  } while (!_gch->no_allocs_since_save_marks(_level));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
bool ParNewGeneration::_avoid_promotion_undo = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
void ParNewGeneration::adjust_desired_tenuring_threshold() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
  // Set the desired survivor size to half the real survivor space
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
  _tenuring_threshold =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
    age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
// A Generation that does parallel young-gen collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
void ParNewGeneration::collect(bool   full,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
                               bool   clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
                               size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
                               bool   is_tlab) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
  assert(full || size > 0, "otherwise we don't want to collect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
    "not a CMS generational heap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
  AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
  _next_gen = gch->next_gen(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
  assert(_next_gen != NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
    "This must be the youngest gen, and not the only gen");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
  assert(gch->n_gens() == 2,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
         "Par collection currently only works with single older gen.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
  // Do we have to avoid promotion_undo?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
  if (gch->collector_policy()->is_concurrent_mark_sweep_policy()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
    set_avoid_promotion_undo(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
  // If the next generation is too full to accomodate worst-case promotion
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
  // from this generation, pass on collection; let the next generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
  // do it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
  if (!collection_attempt_is_safe()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
    gch->set_incremental_collection_will_fail();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
  assert(to()->is_empty(), "Else not collection_attempt_is_safe");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
  init_assuming_no_promotion_failure();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
    set_survivor_overflow(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
    size_policy->minor_collection_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
  TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
  // Capture heap used before collection (for printing).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
  size_t gch_prev_used = gch->used();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
  SpecializationStats::clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
  age_table()->clear();
971
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   730
  to()->clear(SpaceDecorator::Mangle);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
  gch->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
  ParallelTaskTerminator _term(workers->total_workers(), task_queues());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
  ParScanThreadStateSet thread_state_set(workers->total_workers(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
                                         *to(), *this, *_next_gen, *task_queues(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
                                         desired_plab_sz(), _term);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
  ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
  int n_workers = workers->total_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
  gch->set_par_threads(n_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
  gch->change_strong_roots_parity();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
  gch->rem_set()->prepare_for_younger_refs_iterate(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
  // It turns out that even when we're using 1 thread, doing the work in a
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
  // separate thread causes wide variance in run times.  We can't help this
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
  // in the multi-threaded case, but we special-case n=1 here to get
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
  // repeatable measurements of the 1-thread overhead of the parallel code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
  if (n_workers > 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
    workers->run_task(&tsk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
    tsk.work(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
  thread_state_set.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
  if (PAR_STATS_ENABLED && ParallelGCVerbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
    gclog_or_tty->print("Thread totals:\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
               "  Pushes: %7d    Pops: %7d    Steals %7d (sum = %7d).\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
               thread_state_set.pushes(), thread_state_set.pops(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
               thread_state_set.steals(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
               thread_state_set.pops()+thread_state_set.steals());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
  }
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   762
  assert(thread_state_set.pushes() == thread_state_set.pops()
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   763
                                    + thread_state_set.steals(),
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
         "Or else the queues are leaky.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
  // Process (weak) reference objects found during scavenge.
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   767
  ReferenceProcessor* rp = ref_processor();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
  IsAliveClosure is_alive(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
  ScanWeakRefClosure scan_weak_ref(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
  KeepAliveClosure keep_alive(&scan_weak_ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
  ScanClosure               scan_without_gc_barrier(this, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
  ScanClosureWithParBarrier scan_with_gc_barrier(this, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
  set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
  EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
    &scan_without_gc_barrier, &scan_with_gc_barrier);
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   776
  rp->snap_policy(clear_all_soft_refs);
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   777
  if (rp->processing_is_mt()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
    ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   779
    rp->process_discovered_references(&is_alive, &keep_alive,
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   780
                                      &evacuate_followers, &task_executor);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
    thread_state_set.flush();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
    gch->set_par_threads(0);  // 0 ==> non-parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
    gch->save_marks();
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   785
    rp->process_discovered_references(&is_alive, &keep_alive,
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   786
                                      &evacuate_followers, NULL);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
  if (!promotion_failed()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
    // Swap the survivor spaces.
971
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   790
    eden()->clear(SpaceDecorator::Mangle);
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   791
    from()->clear(SpaceDecorator::Mangle);
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   792
    if (ZapUnusedHeapArea) {
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   793
      // This is now done here because of the piece-meal mangling which
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   794
      // can check for valid mangling at intermediate points in the
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   795
      // collection(s).  When a minor collection fails to collect
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   796
      // sufficient space resizing of the young generation can occur
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   797
      // an redistribute the spaces in the young generation.  Mangle
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   798
      // here so that unzapped regions don't get distributed to
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   799
      // other spaces.
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   800
      to()->mangle_unused_area();
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   801
    }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
    swap_spaces();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
    assert(to()->is_empty(), "to space should be empty now");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
    assert(HandlePromotionFailure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
      "Should only be here if promotion failure handling is on");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
    if (_promo_failure_scan_stack != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
      // Can be non-null because of reference processing.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
      // Free stack with its elements.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
      delete _promo_failure_scan_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
      _promo_failure_scan_stack = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
    remove_forwarding_pointers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
    if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
      gclog_or_tty->print(" (promotion failed)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
    // All the spaces are in play for mark-sweep.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
    swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   820
    from()->set_next_compaction_space(to());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
    gch->set_incremental_collection_will_fail();
179
59e3abf83f72 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 1
diff changeset
   822
59e3abf83f72 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 1
diff changeset
   823
    // Reset the PromotionFailureALot counters.
59e3abf83f72 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 1
diff changeset
   824
    NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
  // set new iteration safe limit for the survivor spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
   827
  from()->set_concurrent_iteration_safe_limit(from()->top());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
  to()->set_concurrent_iteration_safe_limit(to()->top());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
  adjust_desired_tenuring_threshold();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
  if (ResizePLAB) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
    plab_stats()->adjust_desired_plab_sz();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
  if (PrintGC && !PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
    gch->print_heap_change(gch_prev_used);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
    size_policy->minor_collection_end(gch->gc_cause());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
    size_policy->avg_survived()->sample(from()->used());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
  update_time_of_last_gc(os::javaTimeMillis());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
  SpecializationStats::print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   848
  rp->set_enqueuing_is_done(true);
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   849
  if (rp->processing_is_mt()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
    ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   851
    rp->enqueue_discovered_references(&task_executor);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
  } else {
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   853
    rp->enqueue_discovered_references(NULL);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
  }
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   855
  rp->verify_no_references_recorded();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
static int sum;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
void ParNewGeneration::waste_some_time() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
  for (int i = 0; i < 100; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
    sum += i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
static const oop ClaimedForwardPtr = oop(0x4);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
// Because of concurrency, there are times where an object for which
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
// "is_forwarded()" is true contains an "interim" forwarding pointer
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
// value.  Such a value will soon be overwritten with a real value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
// This method requires "obj" to have a forwarding pointer, and waits, if
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
// necessary for a real one to be inserted, and returns it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
oop ParNewGeneration::real_forwardee(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
  oop forward_ptr = obj->forwardee();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
  if (forward_ptr != ClaimedForwardPtr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
    return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
    return real_forwardee_slow(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
oop ParNewGeneration::real_forwardee_slow(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
  // Spin-read if it is claimed but not yet written by another thread.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
  oop forward_ptr = obj->forwardee();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
  while (forward_ptr == ClaimedForwardPtr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
    waste_some_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
    assert(obj->is_forwarded(), "precondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
    forward_ptr = obj->forwardee();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
  return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
bool ParNewGeneration::is_legal_forward_ptr(oop p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
  return
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
    (_avoid_promotion_undo && p == ClaimedForwardPtr)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
    || Universe::heap()->is_in_reserved(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
  if ((m != markOopDesc::prototype()) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
      (!UseBiasedLocking || (m != markOopDesc::biased_locking_prototype()))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
    MutexLocker ml(ParGCRareEvent_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
    DefNewGeneration::preserve_mark_if_necessary(obj, m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
// Multiple GC threads may try to promote an object.  If the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
// is successfully promoted, a forwarding pointer will be installed in
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
// the object in the young generation.  This method claims the right
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
// to install the forwarding pointer before it copies the object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   913
// thus avoiding the need to undo the copy as in
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
// copy_to_survivor_space_avoiding_with_undo.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
oop ParNewGeneration::copy_to_survivor_space_avoiding_promotion_undo(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
        ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
  // In the sequential version, this assert also says that the object is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
  // not forwarded.  That might not be the case here.  It is the case that
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
  // the caller observed it to be not forwarded at some time in the past.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
  assert(is_in_reserved(old), "shouldn't be scavenging this oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
489c9b5090e2 Initial load
duke
parents:
diff changeset
   923
  // The sequential code read "old->age()" below.  That doesn't work here,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   924
  // since the age is in the mark word, and that might be overwritten with
489c9b5090e2 Initial load
duke
parents:
diff changeset
   925
  // a forwarding pointer by a parallel thread.  So we must save the mark
489c9b5090e2 Initial load
duke
parents:
diff changeset
   926
  // word in a local and then analyze it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   927
  oopDesc dummyOld;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   928
  dummyOld.set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   929
  assert(!dummyOld.is_forwarded(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   930
         "should not be called with forwarding pointer mark word.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   931
489c9b5090e2 Initial load
duke
parents:
diff changeset
   932
  oop new_obj = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   933
  oop forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   934
489c9b5090e2 Initial load
duke
parents:
diff changeset
   935
  // Try allocating obj in to-space (unless too old)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   936
  if (dummyOld.age() < tenuring_threshold()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   937
    new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   938
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   939
      set_survivor_overflow(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   940
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   941
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   942
489c9b5090e2 Initial load
duke
parents:
diff changeset
   943
  if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   944
    // Either to-space is full or we decided to promote
489c9b5090e2 Initial load
duke
parents:
diff changeset
   945
    // try allocating obj tenured
489c9b5090e2 Initial load
duke
parents:
diff changeset
   946
489c9b5090e2 Initial load
duke
parents:
diff changeset
   947
    // Attempt to install a null forwarding pointer (atomically),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   948
    // to claim the right to install the real forwarding pointer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   949
    forward_ptr = old->forward_to_atomic(ClaimedForwardPtr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   950
    if (forward_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   951
      // someone else beat us to it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   952
        return real_forwardee(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   953
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   954
489c9b5090e2 Initial load
duke
parents:
diff changeset
   955
    new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   956
                                       old, m, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   957
489c9b5090e2 Initial load
duke
parents:
diff changeset
   958
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   959
      if (!HandlePromotionFailure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   960
        // A failed promotion likely means the MaxLiveObjectEvacuationRatio flag
489c9b5090e2 Initial load
duke
parents:
diff changeset
   961
        // is incorrectly set. In any case, its seriously wrong to be here!
489c9b5090e2 Initial load
duke
parents:
diff changeset
   962
        vm_exit_out_of_memory(sz*wordSize, "promotion");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   963
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   964
      // promotion failed, forward to self
489c9b5090e2 Initial load
duke
parents:
diff changeset
   965
      _promotion_failed = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   966
      new_obj = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   967
489c9b5090e2 Initial load
duke
parents:
diff changeset
   968
      preserve_mark_if_necessary(old, m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   969
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   970
489c9b5090e2 Initial load
duke
parents:
diff changeset
   971
    old->forward_to(new_obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   972
    forward_ptr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   973
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   974
    // Is in to-space; do copying ourselves.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   975
    Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   976
    forward_ptr = old->forward_to_atomic(new_obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   977
    // Restore the mark word copied above.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   978
    new_obj->set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   979
    // Increment age if obj still in new generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   980
    new_obj->incr_age();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   981
    par_scan_state->age_table()->add(new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   982
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   983
  assert(new_obj != NULL, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   984
489c9b5090e2 Initial load
duke
parents:
diff changeset
   985
  if (forward_ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   986
    oop obj_to_push = new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   987
    if (par_scan_state->should_be_partially_scanned(obj_to_push, old)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   988
      // Length field used as index of next element to be scanned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   989
      // Real length can be obtained from real_forwardee()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   990
      arrayOop(old)->set_length(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   991
      obj_to_push = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   992
      assert(obj_to_push->is_forwarded() && obj_to_push->forwardee() != obj_to_push,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   993
             "push forwarded object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   994
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   995
    // Push it on one of the queues of to-be-scanned objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   996
    if (!par_scan_state->work_queue()->push(obj_to_push)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   997
      // Add stats for overflow pushes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   998
      if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   999
        gclog_or_tty->print("queue overflow!\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1000
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1001
      push_on_overflow_list(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1002
      par_scan_state->note_overflow_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1003
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1004
    par_scan_state->note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1005
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1006
    return new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1007
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1008
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1009
  // Oops.  Someone beat us to it.  Undo the allocation.  Where did we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1010
  // allocate it?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1011
  if (is_in_reserved(new_obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1012
    // Must be in to_space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1013
    assert(to()->is_in_reserved(new_obj), "Checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1014
    if (forward_ptr == ClaimedForwardPtr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1015
      // Wait to get the real forwarding pointer value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1016
      forward_ptr = real_forwardee(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1017
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1018
    par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1019
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1020
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1021
  return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1022
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1023
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1024
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1025
// Multiple GC threads may try to promote the same object.  If two
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1026
// or more GC threads copy the object, only one wins the race to install
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1027
// the forwarding pointer.  The other threads have to undo their copy.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1028
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1029
oop ParNewGeneration::copy_to_survivor_space_with_undo(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1030
        ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1031
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1032
  // In the sequential version, this assert also says that the object is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1033
  // not forwarded.  That might not be the case here.  It is the case that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1034
  // the caller observed it to be not forwarded at some time in the past.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1035
  assert(is_in_reserved(old), "shouldn't be scavenging this oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1036
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1037
  // The sequential code read "old->age()" below.  That doesn't work here,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1038
  // since the age is in the mark word, and that might be overwritten with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1039
  // a forwarding pointer by a parallel thread.  So we must save the mark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1040
  // word here, install it in a local oopDesc, and then analyze it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1041
  oopDesc dummyOld;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1042
  dummyOld.set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1043
  assert(!dummyOld.is_forwarded(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1044
         "should not be called with forwarding pointer mark word.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1045
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1046
  bool failed_to_promote = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1047
  oop new_obj = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1048
  oop forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1049
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1050
  // Try allocating obj in to-space (unless too old)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1051
  if (dummyOld.age() < tenuring_threshold()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1052
    new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1053
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1054
      set_survivor_overflow(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1055
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1056
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1057
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1058
  if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1059
    // Either to-space is full or we decided to promote
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1060
    // try allocating obj tenured
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1061
    new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1062
                                       old, m, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1063
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1064
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1065
      if (!HandlePromotionFailure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1066
        // A failed promotion likely means the MaxLiveObjectEvacuationRatio
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1067
        // flag is incorrectly set. In any case, its seriously wrong to be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1068
        // here!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1069
        vm_exit_out_of_memory(sz*wordSize, "promotion");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1070
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1071
      // promotion failed, forward to self
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1072
      forward_ptr = old->forward_to_atomic(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1073
      new_obj = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1074
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1075
      if (forward_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1076
        return forward_ptr;   // someone else succeeded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1077
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1078
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1079
      _promotion_failed = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1080
      failed_to_promote = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1081
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1082
      preserve_mark_if_necessary(old, m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1083
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1084
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1085
    // Is in to-space; do copying ourselves.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1086
    Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1087
    // Restore the mark word copied above.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1088
    new_obj->set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1089
    // Increment age if new_obj still in new generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1090
    new_obj->incr_age();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1091
    par_scan_state->age_table()->add(new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1092
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1093
  assert(new_obj != NULL, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1094
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1095
  // Now attempt to install the forwarding pointer (atomically).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1096
  // We have to copy the mark word before overwriting with forwarding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1097
  // ptr, so we can restore it below in the copy.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1098
  if (!failed_to_promote) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1099
    forward_ptr = old->forward_to_atomic(new_obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1100
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1101
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1102
  if (forward_ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1103
    oop obj_to_push = new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1104
    if (par_scan_state->should_be_partially_scanned(obj_to_push, old)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1105
      // Length field used as index of next element to be scanned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1106
      // Real length can be obtained from real_forwardee()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1107
      arrayOop(old)->set_length(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1108
      obj_to_push = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1109
      assert(obj_to_push->is_forwarded() && obj_to_push->forwardee() != obj_to_push,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1110
             "push forwarded object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1111
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1112
    // Push it on one of the queues of to-be-scanned objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1113
    if (!par_scan_state->work_queue()->push(obj_to_push)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1114
      // Add stats for overflow pushes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1115
      push_on_overflow_list(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1116
      par_scan_state->note_overflow_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1117
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1118
    par_scan_state->note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1119
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1120
    return new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1121
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1122
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1123
  // Oops.  Someone beat us to it.  Undo the allocation.  Where did we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1124
  // allocate it?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1125
  if (is_in_reserved(new_obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1126
    // Must be in to_space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1127
    assert(to()->is_in_reserved(new_obj), "Checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1128
    par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1129
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1130
    assert(!_avoid_promotion_undo, "Should not be here if avoiding.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1131
    _next_gen->par_promote_alloc_undo(par_scan_state->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1132
                                      (HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1133
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1134
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1135
  return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1136
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1137
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1138
void ParNewGeneration::push_on_overflow_list(oop from_space_obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1139
  oop cur_overflow_list = _overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1140
  // if the object has been forwarded to itself, then we cannot
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1141
  // use the klass pointer for the linked list.  Instead we have
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1142
  // to allocate an oopDesc in the C-Heap and use that for the linked list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1143
  if (from_space_obj->forwardee() == from_space_obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1144
    oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1145
    listhead->forward_to(from_space_obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1146
    from_space_obj = listhead;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1147
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1148
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1149
    from_space_obj->set_klass_to_list_ptr(cur_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1150
    oop observed_overflow_list =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1151
      (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1152
    if (observed_overflow_list == cur_overflow_list) break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1153
    // Otherwise...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1154
    cur_overflow_list = observed_overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1155
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1156
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1157
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1158
bool
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1159
ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1160
  ObjToScanQueue* work_q = par_scan_state->work_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1161
  // How many to take?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1162
  int objsFromOverflow = MIN2(work_q->max_elems()/4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1163
                              (juint)ParGCDesiredObjsFromOverflowList);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1164
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1165
  if (_overflow_list == NULL) return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1166
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1167
  // Otherwise, there was something there; try claiming the list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1168
  oop prefix = (oop)Atomic::xchg_ptr(NULL, &_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1169
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1170
  if (prefix == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1171
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1172
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1173
  // Trim off a prefix of at most objsFromOverflow items
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1174
  int i = 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1175
  oop cur = prefix;
593
803947e176bd 6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents: 360
diff changeset
  1176
  while (i < objsFromOverflow && cur->klass_or_null() != NULL) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1177
    i++; cur = oop(cur->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1178
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1179
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1180
  // Reattach remaining (suffix) to overflow list
593
803947e176bd 6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents: 360
diff changeset
  1181
  if (cur->klass_or_null() != NULL) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1182
    oop suffix = oop(cur->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1183
    cur->set_klass_to_list_ptr(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1184
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1185
    // Find last item of suffix list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1186
    oop last = suffix;
593
803947e176bd 6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents: 360
diff changeset
  1187
    while (last->klass_or_null() != NULL) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1188
      last = oop(last->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1189
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1190
    // Atomically prepend suffix to current overflow list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1191
    oop cur_overflow_list = _overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1192
    while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1193
      last->set_klass_to_list_ptr(cur_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1194
      oop observed_overflow_list =
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1195
        (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1196
      if (observed_overflow_list == cur_overflow_list) break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1197
      // Otherwise...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1198
      cur_overflow_list = observed_overflow_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1199
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1200
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1201
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1202
  // Push objects on prefix list onto this thread's work queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1203
  assert(cur != NULL, "program logic");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1204
  cur = prefix;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1205
  int n = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1206
  while (cur != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1207
    oop obj_to_push = cur->forwardee();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1208
    oop next        = oop(cur->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1209
    cur->set_klass(obj_to_push->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1210
    if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1211
      obj_to_push = cur;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1212
      assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1213
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1214
    work_q->push(obj_to_push);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1215
    cur = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1216
    n++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1217
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1218
  par_scan_state->note_overflow_refill(n);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1219
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1220
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1221
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1222
void ParNewGeneration::ref_processor_init()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1223
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1224
  if (_ref_processor == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1225
    // Allocate and initialize a reference processor
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1226
    _ref_processor = ReferenceProcessor::create_ref_processor(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1227
        _reserved,                  // span
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1228
        refs_discovery_is_atomic(), // atomic_discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1229
        refs_discovery_is_mt(),     // mt_discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1230
        NULL,                       // is_alive_non_header
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1231
        ParallelGCThreads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1232
        ParallelRefProcEnabled);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1233
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1234
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1235
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1236
const char* ParNewGeneration::name() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1237
  return "par new generation";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1238
}