hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
author ysr
Wed, 23 Dec 2009 09:23:54 -0800
changeset 4574 b2d5b0975515
parent 3908 24b55ad4c228
child 5343 95a5c4b89273
permissions -rw-r--r--
6631166: CMS: better heuristics when combatting fragmentation Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
2105
347008ce7984 6814575: Update copyright year
xdono
parents: 1910
diff changeset
     2
 * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
# include "incls/_precompiled.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
# include "incls/_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_,
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
    37
                                       GrowableArray<oop>**  overflow_stack_set_,
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
                                       size_t desired_plab_sz_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
                                       ParallelTaskTerminator& term_) :
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
    40
  _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_),
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
  _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
    42
  _overflow_stack(overflow_stack_set_[thread_num_]),
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
  _ageTable(false), // false ==> not the global age table, no perf data.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
  _to_space_alloc_buffer(desired_plab_sz_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
  _to_space_closure(gen_, this), _old_gen_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
  _older_gen_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  _evacuate_followers(this, &_to_space_closure, &_old_gen_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
                      &_to_space_root_closure, gen_, &_old_gen_root_closure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
                      work_queue_set_, &term_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
  _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
  _keep_alive_closure(&_scan_weak_ref_closure),
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
    53
  _promotion_failure_size(0),
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  _pushes(0), _pops(0), _steals(0), _steal_attempts(0), _term_attempts(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  _strong_roots_time(0.0), _term_time(0.0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
  _survivor_chunk_array =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
    (ChunkArray*) old_gen()->get_data_recorder(thread_num());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
  _hash_seed = 17;  // Might want to take time-based random value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
  _start = os::elapsedTime();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
  _old_gen_closure.set_generation(old_gen_);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  _old_gen_root_closure.set_generation(old_gen_);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
#ifdef _MSC_VER
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
#pragma warning( pop )
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
void ParScanThreadState::record_survivor_plab(HeapWord* plab_start,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
                                              size_t plab_word_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  ChunkArray* sca = survivor_chunk_array();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  if (sca != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
    // A non-null SCA implies that we want the PLAB data recorded.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
    sca->record_sample(plab_start, plab_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
bool ParScanThreadState::should_be_partially_scanned(oop new_obj, oop old_obj) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  return new_obj->is_objArray() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
         arrayOop(new_obj)->length() > ParGCArrayScanChunk &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
         new_obj != old_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
void ParScanThreadState::scan_partial_array_and_push_remainder(oop old) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  assert(old->is_objArray(), "must be obj array");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  assert(old->is_forwarded(), "must be forwarded");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
  assert(Universe::heap()->is_in_reserved(old), "must be in heap.");
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
    87
  assert(!old_gen()->is_in(old), "must be in young generation.");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
  objArrayOop obj = objArrayOop(old->forwardee());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
  // Process ParGCArrayScanChunk elements now
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
  // and push the remainder back onto queue
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  int start     = arrayOop(old)->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
  int end       = obj->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
  int remainder = end - start;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
  assert(start <= end, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
  if (remainder > 2 * ParGCArrayScanChunk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
    // Test above combines last partial chunk with a full chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
    end = start + ParGCArrayScanChunk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
    arrayOop(old)->set_length(end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
    // Push remainder.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
    bool ok = work_queue()->push(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
    assert(ok, "just popped, push must be okay");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
    // Restore length so that it can be used if there
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
    // is a promotion failure and forwarding pointers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
    // must be removed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
    arrayOop(old)->set_length(end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
  }
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   110
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  // 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
   112
  // should make sure end is even (aligned to HeapWord in case of compressed oops)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  if ((HeapWord *)obj < young_old_boundary()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
    // 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
   115
    obj->oop_iterate_range(&_to_space_closure, start, end);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
    // 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
   118
    obj->oop_iterate_range(&_old_gen_closure, start, end);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
void ParScanThreadState::trim_queues(int max_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
  ObjToScanQueue* queue = work_queue();
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   125
  do {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   126
    while (queue->size() > (juint)max_size) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   127
      oop obj_to_scan;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   128
      if (queue->pop_local(obj_to_scan)) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   129
        note_pop();
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   130
        if ((HeapWord *)obj_to_scan < young_old_boundary()) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   131
          if (obj_to_scan->is_objArray() &&
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   132
              obj_to_scan->is_forwarded() &&
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   133
              obj_to_scan->forwardee() != obj_to_scan) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   134
            scan_partial_array_and_push_remainder(obj_to_scan);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   135
          } else {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   136
            // object is in to_space
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   137
            obj_to_scan->oop_iterate(&_to_space_closure);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   138
          }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
        } else {
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   140
          // object is in old generation
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   141
          obj_to_scan->oop_iterate(&_old_gen_closure);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
    }
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   145
    // For the  case of compressed oops, we have a private, non-shared
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   146
    // overflow stack, so we eagerly drain it so as to more evenly
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   147
    // distribute load early. Note: this may be good to do in
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   148
    // general rather than delay for the final stealing phase.
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   149
    // If applicable, we'll transfer a set of objects over to our
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   150
    // work queue, allowing them to be stolen and draining our
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   151
    // private overflow stack.
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   152
  } while (ParGCTrimOverflow && young_gen()->take_from_overflow_list(this));
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   153
}
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   154
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   155
bool ParScanThreadState::take_from_overflow_stack() {
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   156
  assert(ParGCUseLocalOverflow, "Else should not call");
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   157
  assert(young_gen()->overflow_list() == NULL, "Error");
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   158
  ObjToScanQueue* queue = work_queue();
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   159
  GrowableArray<oop>* of_stack = overflow_stack();
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   160
  uint num_overflow_elems = of_stack->length();
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   161
  uint num_take_elems     = MIN2(MIN2((queue->max_elems() - queue->size())/4,
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   162
                                      (juint)ParGCDesiredObjsFromOverflowList),
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   163
                                 num_overflow_elems);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   164
  // Transfer the most recent num_take_elems from the overflow
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   165
  // stack to our work queue.
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   166
  for (size_t i = 0; i != num_take_elems; i++) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   167
    oop cur = of_stack->pop();
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   168
    oop obj_to_push = cur->forwardee();
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   169
    assert(Universe::heap()->is_in_reserved(cur), "Should be in heap");
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   170
    assert(!old_gen()->is_in_reserved(cur), "Should be in young gen");
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   171
    assert(Universe::heap()->is_in_reserved(obj_to_push), "Should be in heap");
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   172
    if (should_be_partially_scanned(obj_to_push, cur)) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   173
      assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   174
      obj_to_push = cur;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   175
    }
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   176
    bool ok = queue->push(obj_to_push);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   177
    assert(ok, "Should have succeeded");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  }
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   179
  assert(young_gen()->overflow_list() == NULL, "Error");
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   180
  return num_take_elems > 0;  // was something transferred?
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   181
}
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   182
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   183
void ParScanThreadState::push_on_overflow_stack(oop p) {
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   184
  assert(ParGCUseLocalOverflow, "Else should not call");
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   185
  overflow_stack()->push(p);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   186
  assert(young_gen()->overflow_list() == NULL, "Error");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  // Otherwise, if the object is small enough, try to reallocate the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  // buffer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  HeapWord* obj = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
  if (!_to_space_full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
    ParGCAllocBuffer* const plab = to_space_alloc_buffer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
    Space*            const sp   = to_space();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
    if (word_sz * 100 <
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
        ParallelGCBufferWastePct * plab->word_sz()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
      // Is small enough; abandon this buffer and start a new one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
      plab->retire(false, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
      size_t buf_size = plab->word_sz();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
      HeapWord* buf_space = sp->par_allocate(buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
      if (buf_space == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
        const size_t min_bytes =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
          ParGCAllocBuffer::min_size() << LogHeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
        size_t free_bytes = sp->free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
        while(buf_space == NULL && free_bytes >= min_bytes) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
          buf_size = free_bytes >> LogHeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
          assert(buf_size == (size_t)align_object_size(buf_size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
                 "Invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
          buf_space  = sp->par_allocate(buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
          free_bytes = sp->free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
      if (buf_space != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
        plab->set_word_size(buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
        plab->set_buf(buf_space);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
        record_survivor_plab(buf_space, buf_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
        obj = plab->allocate(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
        // Note that we cannot compare buf_size < word_sz below
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
        // because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
        assert(obj != NULL || plab->words_remaining() < word_sz,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
               "Else should have been able to allocate");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
        // It's conceivable that we may be able to use the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
        // buffer we just grabbed for subsequent small requests
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
        // even if not for this one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
        // We're used up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
        _to_space_full = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
      // Too large; allocate the object individually.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
      obj = sp->par_allocate(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  return obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
                                                size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  // Is the alloc in the current alloc buffer?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
  if (to_space_alloc_buffer()->contains(obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
    assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
           "Should contain whole object.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
    to_space_alloc_buffer()->undo_allocation(obj, word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
  } else {
1668
8ec481b8f514 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 1610
diff changeset
   249
    CollectedHeap::fill_with_object(obj, word_sz);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   253
void ParScanThreadState::print_and_clear_promotion_failure_size() {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   254
  if (_promotion_failure_size != 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   255
    if (PrintPromotionFailure) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   256
      gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   257
        _thread_num, _promotion_failure_size);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   258
    }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   259
    _promotion_failure_size = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   260
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   261
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   262
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
class ParScanThreadStateSet: private ResourceArray {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
  // Initializes states for the specified number of threads;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
  ParScanThreadStateSet(int                     num_threads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
                        Space&                  to_space,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
                        ParNewGeneration&       gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
                        Generation&             old_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
                        ObjToScanQueueSet&      queue_set,
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   271
                        GrowableArray<oop>**    overflow_stacks_,
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
                        size_t                  desired_plab_sz,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
                        ParallelTaskTerminator& term);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   274
  inline ParScanThreadState& thread_state(int i);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
  int pushes() { return _pushes; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
  int pops()   { return _pops; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
  int steals() { return _steals; }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   278
  void reset(bool promotion_failed);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
  void flush();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
  ParallelTaskTerminator& _term;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  ParNewGeneration&       _gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
  Generation&             _next_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  // staticstics
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  int _pushes;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
  int _pops;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
  int _steals;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
ParScanThreadStateSet::ParScanThreadStateSet(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
  int num_threads, Space& to_space, ParNewGeneration& gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
  Generation& old_gen, ObjToScanQueueSet& queue_set,
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   294
  GrowableArray<oop>** overflow_stack_set_,
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
  size_t desired_plab_sz, ParallelTaskTerminator& term)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
  : ResourceArray(sizeof(ParScanThreadState), num_threads),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
    _gen(gen), _next_gen(old_gen), _term(term),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
    _pushes(0), _pops(0), _steals(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
  assert(num_threads > 0, "sanity check!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
  // Initialize states.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
  for (int i = 0; i < num_threads; ++i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
    new ((ParScanThreadState*)_data + i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
        ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   305
                           overflow_stack_set_, desired_plab_sz, term);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   309
inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
  assert(i >= 0 && i < length(), "sanity check!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
  return ((ParScanThreadState*)_data)[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   316
void ParScanThreadStateSet::reset(bool promotion_failed)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
  _term.reset_for_reuse();
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   319
  if (promotion_failed) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   320
    for (int i = 0; i < length(); ++i) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   321
      thread_state(i).print_and_clear_promotion_failure_size();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   322
    }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   323
  }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
void ParScanThreadStateSet::flush()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
{
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   328
  // Work in this loop should be kept as lightweight as
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   329
  // possible since this might otherwise become a bottleneck
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   330
  // to scaling. Should we add heavy-weight work into this
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   331
  // loop, consider parallelizing the loop into the worker threads.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
  for (int i = 0; i < length(); ++i) {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   333
    ParScanThreadState& par_scan_state = thread_state(i);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
    // Flush stats related to To-space PLAB activity and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
    // retire the last buffer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
    par_scan_state.to_space_alloc_buffer()->
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
      flush_stats_and_retire(_gen.plab_stats(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
                             false /* !retain */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
    // Every thread has its own age table.  We need to merge
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
    // them all into one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
    ageTable *local_table = par_scan_state.age_table();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
    _gen.age_table()->merge(local_table);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
    // Inform old gen that we're done.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
    _next_gen.par_promote_alloc_done(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
    _next_gen.par_oop_since_save_marks_iterate_done(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
    // Flush stats related to work queue activity (push/pop/steal)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
    // This could conceivably become a bottleneck; if so, we'll put the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
    // stat's gathering under the flag.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
    if (PAR_STATS_ENABLED) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
      _pushes += par_scan_state.pushes();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
      _pops   += par_scan_state.pops();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
      _steals += par_scan_state.steals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
      if (ParallelGCVerbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
        gclog_or_tty->print("Thread %d complete:\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
                            "  Pushes: %7d    Pops: %7d    Steals %7d (in %d attempts)\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
                            i, par_scan_state.pushes(), par_scan_state.pops(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
                            par_scan_state.steals(), par_scan_state.steal_attempts());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
        if (par_scan_state.overflow_pushes() > 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
            par_scan_state.overflow_refills() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
          gclog_or_tty->print("  Overflow pushes: %7d    "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
                              "Overflow refills: %7d for %d objs.\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
                              par_scan_state.overflow_pushes(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
                              par_scan_state.overflow_refills(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
                              par_scan_state.overflow_refill_objs());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
        double elapsed = par_scan_state.elapsed();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
        double strong_roots = par_scan_state.strong_roots_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
        double term = par_scan_state.term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
        gclog_or_tty->print(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
                            "  Elapsed: %7.2f ms.\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
                            "    Strong roots: %7.2f ms (%6.2f%%)\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
                            "    Termination:  %7.2f ms (%6.2f%%) (in %d entries)\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
                           elapsed * 1000.0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
                           strong_roots * 1000.0, (strong_roots*100.0/elapsed),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
                           term * 1000.0, (term*100.0/elapsed),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
                           par_scan_state.term_attempts());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   385
  if (UseConcMarkSweepGC && ParallelGCThreads > 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   386
    // We need to call this even when ResizeOldPLAB is disabled
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   387
    // so as to avoid breaking some asserts. While we may be able
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   388
    // to avoid this by reorganizing the code a bit, I am loathe
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   389
    // to do that unless we find cases where ergo leads to bad
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   390
    // performance.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   391
    CFLS_LAB::compute_desired_plab_size();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   392
  }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
ParScanClosure::ParScanClosure(ParNewGeneration* g,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
                               ParScanThreadState* par_scan_state) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  OopsInGenClosure(g), _par_scan_state(par_scan_state), _g(g)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
  assert(_g->level() == 0, "Optimized for youngest generation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
  _boundary = _g->reserved().end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   403
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
   404
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
   405
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   406
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
   407
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
   408
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   409
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
   410
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
   411
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   412
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
   413
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
   414
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
ParScanWeakRefClosure::ParScanWeakRefClosure(ParNewGeneration* g,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
                                             ParScanThreadState* par_scan_state)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
  : 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
   418
{}
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   419
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   420
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
   421
void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
#ifdef WIN32
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
#pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
ParEvacuateFollowersClosure::ParEvacuateFollowersClosure(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
    ParScanThreadState* par_scan_state_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
    ParScanWithoutBarrierClosure* to_space_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
    ParScanWithBarrierClosure* old_gen_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
    ParRootScanWithoutBarrierClosure* to_space_root_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
    ParNewGeneration* par_gen_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
    ParRootScanWithBarrierTwoGensClosure* old_gen_root_closure_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
    ObjToScanQueueSet* task_queues_,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
    ParallelTaskTerminator* terminator_) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
    _par_scan_state(par_scan_state_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
    _to_space_closure(to_space_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
    _old_gen_closure(old_gen_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
    _to_space_root_closure(to_space_root_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
    _old_gen_root_closure(old_gen_root_closure_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
    _par_gen(par_gen_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
    _task_queues(task_queues_),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
    _terminator(terminator_)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
{}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
void ParEvacuateFollowersClosure::do_void() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  ObjToScanQueue* work_q = par_scan_state()->work_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
    // Scan to-space and old-gen objs until we run out of both.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
    oop obj_to_scan;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
    par_scan_state()->trim_queues(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
    // We have no local work, attempt to steal from other threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
    // attempt to steal work from promoted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
    par_scan_state()->note_steal_attempt();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
    if (task_queues()->steal(par_scan_state()->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
                             par_scan_state()->hash_seed(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
                             obj_to_scan)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
      par_scan_state()->note_steal();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
      bool res = work_q->push(obj_to_scan);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
      assert(res, "Empty queue should have room for a push.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
      par_scan_state()->note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
      //   if successful, goto Start.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
      // try global overflow list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
    } else if (par_gen()->take_from_overflow_list(par_scan_state())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
    // Otherwise, offer termination.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
    par_scan_state()->start_term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
    if (terminator()->offer_termination()) break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
    par_scan_state()->end_term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
  }
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
   481
  assert(par_gen()->_overflow_list == NULL && par_gen()->_num_par_pushes == 0,
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
   482
         "Broken overflow list?");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
  // Finish the last termination pause.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
  par_scan_state()->end_term_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* next_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
                HeapWord* young_old_boundary, ParScanThreadStateSet* state_set) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
    AbstractGangTask("ParNewGeneration collection"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
    _gen(gen), _next_gen(next_gen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
    _young_old_boundary(young_old_boundary),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
    _state_set(state_set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
  {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
void ParNewGenTask::work(int i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
  // Since this is being done in a separate thread, need new resource
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
  // and handle marks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
  HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
  // We would need multiple old-gen queues otherwise.
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
   502
  assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen.");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
  Generation* old_gen = gch->next_gen(_gen);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   506
  ParScanThreadState& par_scan_state = _state_set->thread_state(i);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
  par_scan_state.set_young_old_boundary(_young_old_boundary);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
  par_scan_state.start_strong_roots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
  gch->gen_process_strong_roots(_gen->level(),
3908
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   511
                                true,  // Process younger gens, if any,
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   512
                                       // as strong roots.
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   513
                                false, // no scope; this is parallel code
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   514
                                false, // not collecting perm generation.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
                                SharedHeap::SO_AllClasses,
3908
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   516
                                &par_scan_state.to_space_root_closure(),
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   517
                                true,   // walk *all* scavengable nmethods
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   518
                                &par_scan_state.older_gen_closure());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
  par_scan_state.end_strong_roots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
  // "evacuate followers".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
  par_scan_state.evacuate_followers_closure().do_void();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
#ifdef _MSC_VER
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
#pragma warning( push )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
ParNewGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  : DefNewGeneration(rs, initial_byte_size, level, "PCopy"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  _overflow_list(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
  _is_alive_closure(this),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
  _plab_stats(YoungPLABSize, PLABWeight)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
{
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
   536
  NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;)
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
   537
  NOT_PRODUCT(_num_par_pushes = 0;)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
  _task_queues = new ObjToScanQueueSet(ParallelGCThreads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
  guarantee(_task_queues != NULL, "task_queues allocation failure.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
  for (uint i1 = 0; i1 < ParallelGCThreads; i1++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
    ObjToScanQueuePadded *q_padded = new ObjToScanQueuePadded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
    guarantee(q_padded != NULL, "work_queue Allocation failure.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
    _task_queues->register_queue(i1, &q_padded->work_queue);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
  for (uint i2 = 0; i2 < ParallelGCThreads; i2++)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
    _task_queues->queue(i2)->initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   551
  _overflow_stacks = NEW_C_HEAP_ARRAY(GrowableArray<oop>*, ParallelGCThreads);
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   552
  guarantee(_overflow_stacks != NULL, "Overflow stack set allocation failure");
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   553
  for (uint i = 0; i < ParallelGCThreads; i++) {
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   554
    if (ParGCUseLocalOverflow) {
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   555
      _overflow_stacks[i] = new (ResourceObj::C_HEAP) GrowableArray<oop>(512, true);
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   556
      guarantee(_overflow_stacks[i] != NULL, "Overflow Stack allocation failure.");
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   557
    } else {
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   558
      _overflow_stacks[i] = NULL;
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   559
    }
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   560
  }
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   561
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
    EXCEPTION_MARK;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
    ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
    const char* cname =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
         PerfDataManager::counter_name(_gen_counters->name_space(), "threads");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
                                     ParallelGCThreads, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
#ifdef _MSC_VER
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
#pragma warning( pop )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
// ParNewGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
ParKeepAliveClosure::ParKeepAliveClosure(ParScanWeakRefClosure* cl) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
  DefNewGeneration::KeepAliveClosure(cl), _par_cl(cl) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   580
template <class T>
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   581
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
   582
#ifdef ASSERT
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   583
  {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   584
    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
   585
    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
   586
    // 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
   587
    // as a weak reference.
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   588
    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
   589
  }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   590
#endif // ASSERT
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
  _par_cl->do_oop_nv(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
  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
   595
    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
   596
    _rs->write_ref_field_gc_par(p, obj);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   600
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
   601
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
   602
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
// ParNewGeneration::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
KeepAliveClosure::KeepAliveClosure(ScanWeakRefClosure* cl) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
  DefNewGeneration::KeepAliveClosure(cl) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   607
template <class T>
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   608
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
   609
#ifdef ASSERT
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   610
  {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   611
    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
   612
    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
   613
    // 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
   614
    // as a weak reference.
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   615
    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
   616
  }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   617
#endif // ASSERT
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
  _cl->do_oop_nv(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
  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
   622
    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
   623
    _rs->write_ref_field_gc_par(p, obj);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   627
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
   628
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
   629
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   630
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
   631
  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
   632
  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
   633
    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
    if ((HeapWord*)obj < _boundary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
      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
   636
      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
   637
                      ? obj->forwardee()
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   638
                      : _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
   639
      oopDesc::encode_store_heap_oop_not_null(p, new_obj);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
    if (_gc_barrier) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
      // If p points to a younger generation, mark the card.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
      if ((HeapWord*)obj < _gen_boundary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
        _rs->write_ref_field_gc_par(p, obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 179
diff changeset
   650
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
   651
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
   652
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
class ParNewRefProcTaskProxy: public AbstractGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
  typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
  ParNewRefProcTaskProxy(ProcessTask& task, ParNewGeneration& gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
                         Generation& next_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
                         HeapWord* young_old_boundary,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
                         ParScanThreadStateSet& state_set);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
  virtual void work(int i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
  ParNewGeneration&      _gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
  ProcessTask&           _task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
  Generation&            _next_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
  HeapWord*              _young_old_boundary;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
  ParScanThreadStateSet& _state_set;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
ParNewRefProcTaskProxy::ParNewRefProcTaskProxy(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
    ProcessTask& task, ParNewGeneration& gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
    Generation& next_gen,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
    HeapWord* young_old_boundary,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
    ParScanThreadStateSet& state_set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
  : AbstractGangTask("ParNewGeneration parallel reference processing"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
    _gen(gen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
    _task(task),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
    _next_gen(next_gen),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
    _young_old_boundary(young_old_boundary),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
    _state_set(state_set)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
void ParNewRefProcTaskProxy::work(int i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
  HandleMark hm;
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   690
  ParScanThreadState& par_scan_state = _state_set.thread_state(i);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
  par_scan_state.set_young_old_boundary(_young_old_boundary);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
  _task.work(i, par_scan_state.is_alive_closure(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
             par_scan_state.keep_alive_closure(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
             par_scan_state.evacuate_followers_closure());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
class ParNewRefEnqueueTaskProxy: public AbstractGangTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
  typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
  EnqueueTask& _task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
  ParNewRefEnqueueTaskProxy(EnqueueTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
    : AbstractGangTask("ParNewGeneration parallel reference enqueue"),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
      _task(task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
  { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
  virtual void work(int i)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
    _task.work(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
void ParNewRefProcTaskExecutor::execute(ProcessTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
         "not a generational heap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
  ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
                                 _generation.reserved().end(), _state_set);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
  workers->run_task(&rp_task);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   724
  _state_set.reset(_generation.promotion_failed());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
  ParNewRefEnqueueTaskProxy enq_task(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
  workers->run_task(&enq_task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
void ParNewRefProcTaskExecutor::set_single_threaded_mode()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
  _state_set.flush();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
  gch->set_par_threads(0);  // 0 ==> non-parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
  gch->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
ScanClosureWithParBarrier::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
  ScanClosure(g, gc_barrier) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
EvacuateFollowersClosureGeneral::
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
                                OopsInGenClosure* cur,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
                                OopsInGenClosure* older) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
  _gch(gch), _level(level),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
  _scan_cur_or_nonheap(cur), _scan_older(older)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
{}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
void EvacuateFollowersClosureGeneral::do_void() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
    // Beware: this call will lead to closure applications via virtual
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
    // calls.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
    _gch->oop_since_save_marks_iterate(_level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
                                       _scan_cur_or_nonheap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
                                       _scan_older);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
  } while (!_gch->no_allocs_since_save_marks(_level));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
bool ParNewGeneration::_avoid_promotion_undo = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
void ParNewGeneration::adjust_desired_tenuring_threshold() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
  // Set the desired survivor size to half the real survivor space
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
  _tenuring_threshold =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
    age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
// A Generation that does parallel young-gen collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
void ParNewGeneration::collect(bool   full,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
                               bool   clear_all_soft_refs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
                               size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
                               bool   is_tlab) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
  assert(full || size > 0, "otherwise we don't want to collect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
  GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
    "not a CMS generational heap");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
  AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
  WorkGang* workers = gch->workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
  _next_gen = gch->next_gen(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
  assert(_next_gen != NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
    "This must be the youngest gen, and not the only gen");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
  assert(gch->n_gens() == 2,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
         "Par collection currently only works with single older gen.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
  // Do we have to avoid promotion_undo?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
  if (gch->collector_policy()->is_concurrent_mark_sweep_policy()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
    set_avoid_promotion_undo(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
  // If the next generation is too full to accomodate worst-case promotion
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
  // from this generation, pass on collection; let the next generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
  // do it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
  if (!collection_attempt_is_safe()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
    gch->set_incremental_collection_will_fail();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
  assert(to()->is_empty(), "Else not collection_attempt_is_safe");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
  init_assuming_no_promotion_failure();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
    set_survivor_overflow(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
    size_policy->minor_collection_begin();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
  TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
  // Capture heap used before collection (for printing).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
  size_t gch_prev_used = gch->used();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
  SpecializationStats::clear();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
  age_table()->clear();
971
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   820
  to()->clear(SpaceDecorator::Mangle);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
489c9b5090e2 Initial load
duke
parents:
diff changeset
   822
  gch->save_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   823
  assert(workers != NULL, "Need parallel worker threads.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   824
  ParallelTaskTerminator _term(workers->total_workers(), task_queues());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
  ParScanThreadStateSet thread_state_set(workers->total_workers(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
                                         *to(), *this, *_next_gen, *task_queues(),
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
   827
                                         _overflow_stacks, desired_plab_sz(), _term);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
  ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
  int n_workers = workers->total_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
  gch->set_par_threads(n_workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
  gch->rem_set()->prepare_for_younger_refs_iterate(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
  // It turns out that even when we're using 1 thread, doing the work in a
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
  // separate thread causes wide variance in run times.  We can't help this
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
  // in the multi-threaded case, but we special-case n=1 here to get
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
  // repeatable measurements of the 1-thread overhead of the parallel code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
  if (n_workers > 1) {
3908
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   838
    GenCollectedHeap::StrongRootsScope srs(gch);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
    workers->run_task(&tsk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
  } else {
3908
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2362
diff changeset
   841
    GenCollectedHeap::StrongRootsScope srs(gch);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
    tsk.work(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   844
  thread_state_set.reset(promotion_failed());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
  if (PAR_STATS_ENABLED && ParallelGCVerbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
    gclog_or_tty->print("Thread totals:\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
               "  Pushes: %7d    Pops: %7d    Steals %7d (sum = %7d).\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
               thread_state_set.pushes(), thread_state_set.pops(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
               thread_state_set.steals(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
               thread_state_set.pops()+thread_state_set.steals());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
  }
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   853
  assert(thread_state_set.pushes() == thread_state_set.pops()
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   854
                                    + thread_state_set.steals(),
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
         "Or else the queues are leaky.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
  // Process (weak) reference objects found during scavenge.
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   858
  ReferenceProcessor* rp = ref_processor();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
  IsAliveClosure is_alive(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
  ScanWeakRefClosure scan_weak_ref(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
  KeepAliveClosure keep_alive(&scan_weak_ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
  ScanClosure               scan_without_gc_barrier(this, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
  ScanClosureWithParBarrier scan_with_gc_barrier(this, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
  set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
  EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
    &scan_without_gc_barrier, &scan_with_gc_barrier);
1610
5dddd195cc86 6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
ysr
parents: 1607
diff changeset
   867
  rp->setup_policy(clear_all_soft_refs);
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   868
  if (rp->processing_is_mt()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
    ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   870
    rp->process_discovered_references(&is_alive, &keep_alive,
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   871
                                      &evacuate_followers, &task_executor);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
    thread_state_set.flush();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
    gch->set_par_threads(0);  // 0 ==> non-parallel.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
    gch->save_marks();
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   876
    rp->process_discovered_references(&is_alive, &keep_alive,
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   877
                                      &evacuate_followers, NULL);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
  if (!promotion_failed()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
    // Swap the survivor spaces.
971
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   881
    eden()->clear(SpaceDecorator::Mangle);
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   882
    from()->clear(SpaceDecorator::Mangle);
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   883
    if (ZapUnusedHeapArea) {
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   884
      // 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
   885
      // 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
   886
      // 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
   887
      // 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
   888
      // 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
   889
      // 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
   890
      // other spaces.
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   891
      to()->mangle_unused_area();
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 593
diff changeset
   892
    }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
    swap_spaces();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
    assert(to()->is_empty(), "to space should be empty now");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
    assert(HandlePromotionFailure,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
      "Should only be here if promotion failure handling is on");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
    if (_promo_failure_scan_stack != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
      // Can be non-null because of reference processing.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
      // Free stack with its elements.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
      delete _promo_failure_scan_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
      _promo_failure_scan_stack = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
    remove_forwarding_pointers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
    if (PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
      gclog_or_tty->print(" (promotion failed)");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
    // All the spaces are in play for mark-sweep.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
    swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
    from()->set_next_compaction_space(to());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
    gch->set_incremental_collection_will_fail();
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   913
    // Inform the next generation that a promotion failure occurred.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
   914
    _next_gen->promotion_failure_occurred();
179
59e3abf83f72 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 1
diff changeset
   915
59e3abf83f72 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 1
diff changeset
   916
    // Reset the PromotionFailureALot counters.
59e3abf83f72 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 1
diff changeset
   917
    NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
  // set new iteration safe limit for the survivor spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
  from()->set_concurrent_iteration_safe_limit(from()->top());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
  to()->set_concurrent_iteration_safe_limit(to()->top());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
489c9b5090e2 Initial load
duke
parents:
diff changeset
   923
  adjust_desired_tenuring_threshold();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   924
  if (ResizePLAB) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   925
    plab_stats()->adjust_desired_plab_sz();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   926
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   927
489c9b5090e2 Initial load
duke
parents:
diff changeset
   928
  if (PrintGC && !PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   929
    gch->print_heap_change(gch_prev_used);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   930
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   931
489c9b5090e2 Initial load
duke
parents:
diff changeset
   932
  if (UseAdaptiveSizePolicy) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   933
    size_policy->minor_collection_end(gch->gc_cause());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   934
    size_policy->avg_survived()->sample(from()->used());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   935
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   936
489c9b5090e2 Initial load
duke
parents:
diff changeset
   937
  update_time_of_last_gc(os::javaTimeMillis());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   938
489c9b5090e2 Initial load
duke
parents:
diff changeset
   939
  SpecializationStats::print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   940
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   941
  rp->set_enqueuing_is_done(true);
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   942
  if (rp->processing_is_mt()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   943
    ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   944
    rp->enqueue_discovered_references(&task_executor);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   945
  } else {
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   946
    rp->enqueue_discovered_references(NULL);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   947
  }
1606
dcf9714addbe 6684579: SoftReference processing can be made more efficient
ysr
parents: 977
diff changeset
   948
  rp->verify_no_references_recorded();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   949
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   950
489c9b5090e2 Initial load
duke
parents:
diff changeset
   951
static int sum;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   952
void ParNewGeneration::waste_some_time() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   953
  for (int i = 0; i < 100; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   954
    sum += i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   955
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   956
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   957
489c9b5090e2 Initial load
duke
parents:
diff changeset
   958
static const oop ClaimedForwardPtr = oop(0x4);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   959
489c9b5090e2 Initial load
duke
parents:
diff changeset
   960
// Because of concurrency, there are times where an object for which
489c9b5090e2 Initial load
duke
parents:
diff changeset
   961
// "is_forwarded()" is true contains an "interim" forwarding pointer
489c9b5090e2 Initial load
duke
parents:
diff changeset
   962
// value.  Such a value will soon be overwritten with a real value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   963
// This method requires "obj" to have a forwarding pointer, and waits, if
489c9b5090e2 Initial load
duke
parents:
diff changeset
   964
// necessary for a real one to be inserted, and returns it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   965
489c9b5090e2 Initial load
duke
parents:
diff changeset
   966
oop ParNewGeneration::real_forwardee(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   967
  oop forward_ptr = obj->forwardee();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   968
  if (forward_ptr != ClaimedForwardPtr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   969
    return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   970
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   971
    return real_forwardee_slow(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   972
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   973
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   974
489c9b5090e2 Initial load
duke
parents:
diff changeset
   975
oop ParNewGeneration::real_forwardee_slow(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   976
  // Spin-read if it is claimed but not yet written by another thread.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   977
  oop forward_ptr = obj->forwardee();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   978
  while (forward_ptr == ClaimedForwardPtr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   979
    waste_some_time();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   980
    assert(obj->is_forwarded(), "precondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   981
    forward_ptr = obj->forwardee();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   982
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   983
  return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   984
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   985
489c9b5090e2 Initial load
duke
parents:
diff changeset
   986
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   987
bool ParNewGeneration::is_legal_forward_ptr(oop p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   988
  return
489c9b5090e2 Initial load
duke
parents:
diff changeset
   989
    (_avoid_promotion_undo && p == ClaimedForwardPtr)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   990
    || Universe::heap()->is_in_reserved(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   991
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   992
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   993
489c9b5090e2 Initial load
duke
parents:
diff changeset
   994
void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   995
  if ((m != markOopDesc::prototype()) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   996
      (!UseBiasedLocking || (m != markOopDesc::biased_locking_prototype()))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   997
    MutexLocker ml(ParGCRareEvent_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   998
    DefNewGeneration::preserve_mark_if_necessary(obj, m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   999
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1000
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1001
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1002
// Multiple GC threads may try to promote an object.  If the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1003
// is successfully promoted, a forwarding pointer will be installed in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1004
// the object in the young generation.  This method claims the right
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1005
// to install the forwarding pointer before it copies the object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1006
// thus avoiding the need to undo the copy as in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1007
// copy_to_survivor_space_avoiding_with_undo.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1008
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1009
oop ParNewGeneration::copy_to_survivor_space_avoiding_promotion_undo(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1010
        ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1011
  // In the sequential version, this assert also says that the object is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1012
  // not forwarded.  That might not be the case here.  It is the case that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1013
  // the caller observed it to be not forwarded at some time in the past.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1014
  assert(is_in_reserved(old), "shouldn't be scavenging this oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1015
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1016
  // The sequential code read "old->age()" below.  That doesn't work here,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1017
  // since the age is in the mark word, and that might be overwritten with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1018
  // a forwarding pointer by a parallel thread.  So we must save the mark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1019
  // word in a local and then analyze it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1020
  oopDesc dummyOld;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1021
  dummyOld.set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1022
  assert(!dummyOld.is_forwarded(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1023
         "should not be called with forwarding pointer mark word.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1024
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1025
  oop new_obj = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1026
  oop forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1027
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1028
  // Try allocating obj in to-space (unless too old)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1029
  if (dummyOld.age() < tenuring_threshold()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1030
    new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1031
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1032
      set_survivor_overflow(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1033
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1034
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1035
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1036
  if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1037
    // Either to-space is full or we decided to promote
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1038
    // try allocating obj tenured
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1039
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1040
    // Attempt to install a null forwarding pointer (atomically),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1041
    // to claim the right to install the real forwarding pointer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1042
    forward_ptr = old->forward_to_atomic(ClaimedForwardPtr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1043
    if (forward_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1044
      // someone else beat us to it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1045
        return real_forwardee(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1046
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1047
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1048
    new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1049
                                       old, m, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1050
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1051
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1052
      if (!HandlePromotionFailure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1053
        // A failed promotion likely means the MaxLiveObjectEvacuationRatio flag
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1054
        // is incorrectly set. In any case, its seriously wrong to be here!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1055
        vm_exit_out_of_memory(sz*wordSize, "promotion");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1056
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1057
      // promotion failed, forward to self
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1058
      _promotion_failed = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1059
      new_obj = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1060
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1061
      preserve_mark_if_necessary(old, m);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
  1062
      // Log the size of the maiden promotion failure
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
  1063
      par_scan_state->log_promotion_failure(sz);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1064
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1065
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1066
    old->forward_to(new_obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1067
    forward_ptr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1068
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1069
    // Is in to-space; do copying ourselves.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1070
    Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1071
    forward_ptr = old->forward_to_atomic(new_obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1072
    // Restore the mark word copied above.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1073
    new_obj->set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1074
    // Increment age if obj still in new generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1075
    new_obj->incr_age();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1076
    par_scan_state->age_table()->add(new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1077
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1078
  assert(new_obj != NULL, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1079
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1080
  if (forward_ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1081
    oop obj_to_push = new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1082
    if (par_scan_state->should_be_partially_scanned(obj_to_push, old)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1083
      // Length field used as index of next element to be scanned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1084
      // Real length can be obtained from real_forwardee()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1085
      arrayOop(old)->set_length(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1086
      obj_to_push = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1087
      assert(obj_to_push->is_forwarded() && obj_to_push->forwardee() != obj_to_push,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1088
             "push forwarded object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1089
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1090
    // Push it on one of the queues of to-be-scanned objects.
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1091
    bool simulate_overflow = false;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1092
    NOT_PRODUCT(
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1093
      if (ParGCWorkQueueOverflowALot && should_simulate_overflow()) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1094
        // simulate a stack overflow
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1095
        simulate_overflow = true;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1096
      }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1097
    )
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1098
    if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1099
      // Add stats for overflow pushes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1100
      if (Verbose && PrintGCDetails) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1101
        gclog_or_tty->print("queue overflow!\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1102
      }
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1103
      push_on_overflow_list(old, par_scan_state);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1104
      par_scan_state->note_overflow_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1105
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1106
    par_scan_state->note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1107
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1108
    return new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1109
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1110
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1111
  // Oops.  Someone beat us to it.  Undo the allocation.  Where did we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1112
  // allocate it?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1113
  if (is_in_reserved(new_obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1114
    // Must be in to_space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1115
    assert(to()->is_in_reserved(new_obj), "Checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1116
    if (forward_ptr == ClaimedForwardPtr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1117
      // Wait to get the real forwarding pointer value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1118
      forward_ptr = real_forwardee(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1119
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1120
    par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1121
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1122
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1123
  return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1124
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1125
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1126
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1127
// Multiple GC threads may try to promote the same object.  If two
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1128
// or more GC threads copy the object, only one wins the race to install
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1129
// the forwarding pointer.  The other threads have to undo their copy.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1130
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1131
oop ParNewGeneration::copy_to_survivor_space_with_undo(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1132
        ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1133
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1134
  // In the sequential version, this assert also says that the object is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1135
  // not forwarded.  That might not be the case here.  It is the case that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1136
  // the caller observed it to be not forwarded at some time in the past.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1137
  assert(is_in_reserved(old), "shouldn't be scavenging this oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1138
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1139
  // The sequential code read "old->age()" below.  That doesn't work here,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1140
  // since the age is in the mark word, and that might be overwritten with
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1141
  // a forwarding pointer by a parallel thread.  So we must save the mark
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1142
  // word here, install it in a local oopDesc, and then analyze it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1143
  oopDesc dummyOld;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1144
  dummyOld.set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1145
  assert(!dummyOld.is_forwarded(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1146
         "should not be called with forwarding pointer mark word.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1147
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1148
  bool failed_to_promote = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1149
  oop new_obj = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1150
  oop forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1151
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1152
  // Try allocating obj in to-space (unless too old)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1153
  if (dummyOld.age() < tenuring_threshold()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1154
    new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1155
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1156
      set_survivor_overflow(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1157
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1158
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1160
  if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1161
    // Either to-space is full or we decided to promote
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1162
    // try allocating obj tenured
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1163
    new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1164
                                       old, m, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1165
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1166
    if (new_obj == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1167
      if (!HandlePromotionFailure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1168
        // A failed promotion likely means the MaxLiveObjectEvacuationRatio
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1169
        // flag is incorrectly set. In any case, its seriously wrong to be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1170
        // here!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1171
        vm_exit_out_of_memory(sz*wordSize, "promotion");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1172
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1173
      // promotion failed, forward to self
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1174
      forward_ptr = old->forward_to_atomic(old);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1175
      new_obj = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1176
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1177
      if (forward_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1178
        return forward_ptr;   // someone else succeeded
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1179
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1180
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1181
      _promotion_failed = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1182
      failed_to_promote = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1183
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1184
      preserve_mark_if_necessary(old, m);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
  1185
      // Log the size of the maiden promotion failure
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 3908
diff changeset
  1186
      par_scan_state->log_promotion_failure(sz);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1187
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1188
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1189
    // Is in to-space; do copying ourselves.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1190
    Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1191
    // Restore the mark word copied above.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1192
    new_obj->set_mark(m);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1193
    // Increment age if new_obj still in new generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1194
    new_obj->incr_age();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1195
    par_scan_state->age_table()->add(new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1196
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1197
  assert(new_obj != NULL, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1198
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1199
  // Now attempt to install the forwarding pointer (atomically).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1200
  // We have to copy the mark word before overwriting with forwarding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1201
  // ptr, so we can restore it below in the copy.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1202
  if (!failed_to_promote) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1203
    forward_ptr = old->forward_to_atomic(new_obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1204
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1205
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1206
  if (forward_ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1207
    oop obj_to_push = new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1208
    if (par_scan_state->should_be_partially_scanned(obj_to_push, old)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1209
      // Length field used as index of next element to be scanned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1210
      // Real length can be obtained from real_forwardee()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1211
      arrayOop(old)->set_length(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1212
      obj_to_push = old;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1213
      assert(obj_to_push->is_forwarded() && obj_to_push->forwardee() != obj_to_push,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1214
             "push forwarded object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1215
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1216
    // Push it on one of the queues of to-be-scanned objects.
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1217
    bool simulate_overflow = false;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1218
    NOT_PRODUCT(
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1219
      if (ParGCWorkQueueOverflowALot && should_simulate_overflow()) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1220
        // simulate a stack overflow
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1221
        simulate_overflow = true;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1222
      }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1223
    )
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1224
    if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1225
      // Add stats for overflow pushes.
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1226
      push_on_overflow_list(old, par_scan_state);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1227
      par_scan_state->note_overflow_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1228
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1229
    par_scan_state->note_push();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1230
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1231
    return new_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1232
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1233
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1234
  // Oops.  Someone beat us to it.  Undo the allocation.  Where did we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1235
  // allocate it?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1236
  if (is_in_reserved(new_obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1237
    // Must be in to_space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1238
    assert(to()->is_in_reserved(new_obj), "Checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1239
    par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1240
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1241
    assert(!_avoid_promotion_undo, "Should not be here if avoiding.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1242
    _next_gen->par_promote_alloc_undo(par_scan_state->thread_num(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1243
                                      (HeapWord*)new_obj, sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1244
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1245
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1246
  return forward_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1247
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1248
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1249
#ifndef PRODUCT
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1250
// It's OK to call this multi-threaded;  the worst thing
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1251
// that can happen is that we'll get a bunch of closely
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1252
// spaced simulated oveflows, but that's OK, in fact
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1253
// probably good as it would exercise the overflow code
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1254
// under contention.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1255
bool ParNewGeneration::should_simulate_overflow() {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1256
  if (_overflow_counter-- <= 0) { // just being defensive
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1257
    _overflow_counter = ParGCWorkQueueOverflowInterval;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1258
    return true;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1259
  } else {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1260
    return false;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1261
  }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1262
}
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1263
#endif
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1264
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1265
// In case we are using compressed oops, we need to be careful.
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1266
// If the object being pushed is an object array, then its length
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1267
// field keeps track of the "grey boundary" at which the next
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1268
// incremental scan will be done (see ParGCArrayScanChunk).
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1269
// When using compressed oops, this length field is kept in the
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1270
// lower 32 bits of the erstwhile klass word and cannot be used
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1271
// for the overflow chaining pointer (OCP below). As such the OCP
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1272
// would itself need to be compressed into the top 32-bits in this
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1273
// case. Unfortunately, see below, in the event that we have a
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1274
// promotion failure, the node to be pushed on the list can be
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1275
// outside of the Java heap, so the heap-based pointer compression
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1276
// would not work (we would have potential aliasing between C-heap
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1277
// and Java-heap pointers). For this reason, when using compressed
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1278
// oops, we simply use a worker-thread-local, non-shared overflow
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1279
// list in the form of a growable array, with a slightly different
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1280
// overflow stack draining strategy. If/when we start using fat
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1281
// stacks here, we can go back to using (fat) pointer chains
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1282
// (although some performance comparisons would be useful since
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1283
// single global lists have their own performance disadvantages
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1284
// as we were made painfully aware not long ago, see 6786503).
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1285
#define BUSY (oop(0x1aff1aff))
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1286
void ParNewGeneration::push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state) {
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1287
  assert(is_in_reserved(from_space_obj), "Should be from this generation");
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
  1288
  if (ParGCUseLocalOverflow) {
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1289
    // In the case of compressed oops, we use a private, not-shared
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1290
    // overflow stack.
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1291
    par_scan_state->push_on_overflow_stack(from_space_obj);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1292
  } else {
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
  1293
    assert(!UseCompressedOops, "Error");
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1294
    // if the object has been forwarded to itself, then we cannot
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1295
    // use the klass pointer for the linked list.  Instead we have
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1296
    // to allocate an oopDesc in the C-Heap and use that for the linked list.
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1297
    // XXX This is horribly inefficient when a promotion failure occurs
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1298
    // and should be fixed. XXX FIX ME !!!
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1299
#ifndef PRODUCT
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1300
    Atomic::inc_ptr(&_num_par_pushes);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1301
    assert(_num_par_pushes > 0, "Tautology");
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1302
#endif
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1303
    if (from_space_obj->forwardee() == from_space_obj) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1304
      oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1305
      listhead->forward_to(from_space_obj);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1306
      from_space_obj = listhead;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1307
    }
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1308
    oop observed_overflow_list = _overflow_list;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1309
    oop cur_overflow_list;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1310
    do {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1311
      cur_overflow_list = observed_overflow_list;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1312
      if (cur_overflow_list != BUSY) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1313
        from_space_obj->set_klass_to_list_ptr(cur_overflow_list);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1314
      } else {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1315
        from_space_obj->set_klass_to_list_ptr(NULL);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1316
      }
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1317
      observed_overflow_list =
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1318
        (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1319
    } while (cur_overflow_list != observed_overflow_list);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1320
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1321
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1322
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1323
bool ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1324
  bool res;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1325
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
  1326
  if (ParGCUseLocalOverflow) {
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1327
    res = par_scan_state->take_from_overflow_stack();
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1328
  } else {
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
  1329
    assert(!UseCompressedOops, "Error");
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1330
    res = take_from_overflow_list_work(par_scan_state);
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1331
  }
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1332
  return res;
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1333
}
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1334
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1335
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1336
// *NOTE*: The overflow list manipulation code here and
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1337
// in CMSCollector:: are very similar in shape,
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1338
// except that in the CMS case we thread the objects
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1339
// directly into the list via their mark word, and do
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1340
// not need to deal with special cases below related
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1341
// to chunking of object arrays and promotion failure
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1342
// handling.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1343
// CR 6797058 has been filed to attempt consolidation of
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1344
// the common code.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1345
// Because of the common code, if you make any changes in
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1346
// the code below, please check the CMS version to see if
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1347
// similar changes might be needed.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1348
// See CMSCollector::par_take_from_overflow_list() for
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1349
// more extensive documentation comments.
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1350
bool ParNewGeneration::take_from_overflow_list_work(ParScanThreadState* par_scan_state) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1351
  ObjToScanQueue* work_q = par_scan_state->work_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1352
  // How many to take?
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1353
  size_t objsFromOverflow = MIN2((size_t)(work_q->max_elems() - work_q->size())/4,
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1354
                                 (size_t)ParGCDesiredObjsFromOverflowList);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1355
2346
3aa355016e90 6819891: ParNew: Fix work queue overflow code to deal correctly with +UseCompressedOops
ysr
parents: 2105
diff changeset
  1356
  assert(par_scan_state->overflow_stack() == NULL, "Error");
2362
5e1bfddf919e 6824570: ParNew: Fix memory leak introduced in 6819891
ysr
parents: 2346
diff changeset
  1357
  assert(!UseCompressedOops, "Error");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1358
  if (_overflow_list == NULL) return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1359
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1360
  // Otherwise, there was something there; try claiming the list.
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1361
  oop prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1362
  // Trim off a prefix of at most objsFromOverflow items
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1363
  Thread* tid = Thread::current();
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1364
  size_t spin_count = (size_t)ParallelGCThreads;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1365
  size_t sleep_time_millis = MAX2((size_t)1, objsFromOverflow/100);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1366
  for (size_t spin = 0; prefix == BUSY && spin < spin_count; spin++) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1367
    // someone grabbed it before we did ...
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1368
    // ... we spin for a short while...
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1369
    os::sleep(tid, sleep_time_millis, false);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1370
    if (_overflow_list == NULL) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1371
      // nothing left to take
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1372
      return false;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1373
    } else if (_overflow_list != BUSY) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1374
     // try and grab the prefix
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1375
     prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1376
    }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1377
  }
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1378
  if (prefix == NULL || prefix == BUSY) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1379
     // Nothing to take or waited long enough
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1380
     if (prefix == NULL) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1381
       // Write back the NULL in case we overwrote it with BUSY above
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1382
       // and it is still the same value.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1383
       (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1384
     }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1385
     return false;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1386
  }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1387
  assert(prefix != NULL && prefix != BUSY, "Error");
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1388
  size_t i = 1;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1389
  oop cur = prefix;
593
803947e176bd 6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents: 360
diff changeset
  1390
  while (i < objsFromOverflow && cur->klass_or_null() != NULL) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1391
    i++; cur = oop(cur->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1392
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1393
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1394
  // Reattach remaining (suffix) to overflow list
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1395
  if (cur->klass_or_null() == NULL) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1396
    // Write back the NULL in lieu of the BUSY we wrote
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1397
    // above and it is still the same value.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1398
    if (_overflow_list == BUSY) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1399
      (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1400
    }
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1401
  } else {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1402
    assert(cur->klass_or_null() != BUSY, "Error");
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1403
    oop suffix = oop(cur->klass());       // suffix will be put back on global list
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1404
    cur->set_klass_to_list_ptr(NULL);     // break off suffix
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1405
    // It's possible that the list is still in the empty(busy) state
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1406
    // we left it in a short while ago; in that case we may be
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1407
    // able to place back the suffix.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1408
    oop observed_overflow_list = _overflow_list;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1409
    oop cur_overflow_list = observed_overflow_list;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1410
    bool attached = false;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1411
    while (observed_overflow_list == BUSY || observed_overflow_list == NULL) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1412
      observed_overflow_list =
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1413
        (oop) Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1414
      if (cur_overflow_list == observed_overflow_list) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1415
        attached = true;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1416
        break;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1417
      } else cur_overflow_list = observed_overflow_list;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1418
    }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1419
    if (!attached) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1420
      // Too bad, someone else got in in between; we'll need to do a splice.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1421
      // Find the last item of suffix list
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1422
      oop last = suffix;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1423
      while (last->klass_or_null() != NULL) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1424
        last = oop(last->klass());
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1425
      }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1426
      // Atomically prepend suffix to current overflow list
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1427
      observed_overflow_list = _overflow_list;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1428
      do {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1429
        cur_overflow_list = observed_overflow_list;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1430
        if (cur_overflow_list != BUSY) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1431
          // Do the splice ...
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1432
          last->set_klass_to_list_ptr(cur_overflow_list);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1433
        } else { // cur_overflow_list == BUSY
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1434
          last->set_klass_to_list_ptr(NULL);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1435
        }
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1436
        observed_overflow_list =
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1437
          (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1438
      } while (cur_overflow_list != observed_overflow_list);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1439
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1440
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1441
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1442
  // Push objects on prefix list onto this thread's work queue
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1443
  assert(prefix != NULL && prefix != BUSY, "program logic");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1444
  cur = prefix;
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1445
  ssize_t n = 0;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1446
  while (cur != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1447
    oop obj_to_push = cur->forwardee();
1607
be7d05bc07b2 6774607: SIGSEGV or (!is_null(v),"oop value can never be zero") assertion when running with CMS and COOPs
ysr
parents: 1606
diff changeset
  1448
    oop next        = oop(cur->klass_or_null());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1449
    cur->set_klass(obj_to_push->klass());
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1450
    // This may be an array object that is self-forwarded. In that case, the list pointer
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1451
    // space, cur, is not in the Java heap, but rather in the C-heap and should be freed.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1452
    if (!is_in_reserved(cur)) {
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1453
      // This can become a scaling bottleneck when there is work queue overflow coincident
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1454
      // with promotion failure.
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1455
      oopDesc* f = cur;
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1456
      FREE_C_HEAP_ARRAY(oopDesc, f);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1457
    } else if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1458
      assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1459
      obj_to_push = cur;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1460
    }
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1461
    bool ok = work_q->push(obj_to_push);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1462
    assert(ok, "Should have succeeded");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1463
    cur = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1464
    n++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1465
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1466
  par_scan_state->note_overflow_refill(n);
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1467
#ifndef PRODUCT
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1468
  assert(_num_par_pushes >= n, "Too many pops?");
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1469
  Atomic::add_ptr(-(intptr_t)n, &_num_par_pushes);
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1470
#endif
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1471
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1472
}
1910
386106352d02 6786503: Overflow list performance can be improved
ysr
parents: 1668
diff changeset
  1473
#undef BUSY
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1474
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1475
void ParNewGeneration::ref_processor_init()
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1476
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1477
  if (_ref_processor == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1478
    // Allocate and initialize a reference processor
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1479
    _ref_processor = ReferenceProcessor::create_ref_processor(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1480
        _reserved,                  // span
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1481
        refs_discovery_is_atomic(), // atomic_discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1482
        refs_discovery_is_mt(),     // mt_discovery
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1483
        NULL,                       // is_alive_non_header
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1484
        ParallelGCThreads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1485
        ParallelRefProcEnabled);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1486
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1487
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1488
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1489
const char* ParNewGeneration::name() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1490
  return "par new generation";
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1491
}