psCompactionManager.cpp 10.7 KB
Newer Older
D
duke 已提交
1
/*
X
xdono 已提交
2
 * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

#include "incls/_precompiled.incl"
#include "incls/_psCompactionManager.cpp.incl"

PSOldGen*            ParCompactionManager::_old_gen = NULL;
ParCompactionManager**  ParCompactionManager::_manager_array = NULL;
OopTaskQueueSet*     ParCompactionManager::_stack_array = NULL;
ObjectStartArray*    ParCompactionManager::_start_array = NULL;
ParMarkBitMap*       ParCompactionManager::_mark_bitmap = NULL;
33
RegionTaskQueueSet*   ParCompactionManager::_region_array = NULL;
D
duke 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

ParCompactionManager::ParCompactionManager() :
    _action(CopyAndUpdate) {

  ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
  assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");

  _old_gen = heap->old_gen();
  _start_array = old_gen()->start_array();


  marking_stack()->initialize();

  // We want the overflow stack to be permanent
  _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
49 50
#ifdef USE_RegionTaskQueueWithOverflow
  region_stack()->initialize();
D
duke 已提交
51
#else
52
  region_stack()->initialize();
D
duke 已提交
53 54

  // We want the overflow stack to be permanent
55
  _region_overflow_stack =
D
duke 已提交
56 57 58 59 60 61 62 63
    new (ResourceObj::C_HEAP) GrowableArray<size_t>(10, true);
#endif

  // Note that _revisit_klass_stack is allocated out of the
  // C heap (as opposed to out of ResourceArena).
  int size =
    (SystemDictionary::number_of_classes() * 2) * 2 / ParallelGCThreads;
  _revisit_klass_stack = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(size, true);
Y
ysr 已提交
64 65 66
  // From some experiments (#klass/k)^2 for k = 10 seems a better fit, but this will
  // have to do for now until we are able to investigate a more optimal setting.
  _revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true);
D
duke 已提交
67 68 69 70 71 72

}

ParCompactionManager::~ParCompactionManager() {
  delete _overflow_stack;
  delete _revisit_klass_stack;
Y
ysr 已提交
73
  delete _revisit_mdo_stack;
D
duke 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
  // _manager_array and _stack_array are statics
  // shared with all instances of ParCompactionManager
  // should not be deallocated.
}

void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
  assert(PSParallelCompact::gc_task_manager() != NULL,
    "Needed for initialization");

  _mark_bitmap = mbm;

  uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();

  assert(_manager_array == NULL, "Attempt to initialize twice");
  _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 );
  guarantee(_manager_array != NULL, "Could not initialize promotion manager");

  _stack_array = new OopTaskQueueSet(parallel_gc_threads);
  guarantee(_stack_array != NULL, "Count not initialize promotion manager");
93 94
  _region_array = new RegionTaskQueueSet(parallel_gc_threads);
  guarantee(_region_array != NULL, "Count not initialize promotion manager");
D
duke 已提交
95 96 97 98 99 100

  // Create and register the ParCompactionManager(s) for the worker threads.
  for(uint i=0; i<parallel_gc_threads; i++) {
    _manager_array[i] = new ParCompactionManager();
    guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");
    stack_array()->register_queue(i, _manager_array[i]->marking_stack());
101 102
#ifdef USE_RegionTaskQueueWithOverflow
    region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue());
D
duke 已提交
103
#else
104
    region_array()->register_queue(i, _manager_array[i]->region_stack());
D
duke 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
#endif
  }

  // The VMThread gets its own ParCompactionManager, which is not available
  // for work stealing.
  _manager_array[parallel_gc_threads] = new ParCompactionManager();
  guarantee(_manager_array[parallel_gc_threads] != NULL,
    "Could not create ParCompactionManager");
  assert(PSParallelCompact::gc_task_manager()->workers() != 0,
    "Not initialized?");
}

bool ParCompactionManager::should_update() {
  assert(action() != NotValid, "Action is not set");
  return (action() == ParCompactionManager::Update) ||
         (action() == ParCompactionManager::CopyAndUpdate) ||
         (action() == ParCompactionManager::UpdateAndCopy);
}

bool ParCompactionManager::should_copy() {
  assert(action() != NotValid, "Action is not set");
  return (action() == ParCompactionManager::Copy) ||
         (action() == ParCompactionManager::CopyAndUpdate) ||
         (action() == ParCompactionManager::UpdateAndCopy);
}

bool ParCompactionManager::should_verify_only() {
  assert(action() != NotValid, "Action is not set");
  return action() == ParCompactionManager::VerifyUpdate;
}

bool ParCompactionManager::should_reset_only() {
  assert(action() != NotValid, "Action is not set");
  return action() == ParCompactionManager::ResetObjects;
}

// For now save on a stack
void ParCompactionManager::save_for_scanning(oop m) {
  stack_push(m);
}

void ParCompactionManager::stack_push(oop obj) {

  if(!marking_stack()->push(obj)) {
    overflow_stack()->push(obj);
  }
}

oop ParCompactionManager::retrieve_for_scanning() {

  // Should not be used in the parallel case
  ShouldNotReachHere();
  return NULL;
}

160 161
// Save region on a stack
void ParCompactionManager::save_for_processing(size_t region_index) {
D
duke 已提交
162 163
#ifdef ASSERT
  const ParallelCompactData& sd = PSParallelCompact::summary_data();
164 165 166
  ParallelCompactData::RegionData* const region_ptr = sd.region(region_index);
  assert(region_ptr->claimed(), "must be claimed");
  assert(region_ptr->_pushed++ == 0, "should only be pushed once");
D
duke 已提交
167
#endif
168
  region_stack_push(region_index);
D
duke 已提交
169 170
}

171
void ParCompactionManager::region_stack_push(size_t region_index) {
D
duke 已提交
172

173 174
#ifdef USE_RegionTaskQueueWithOverflow
  region_stack()->save(region_index);
D
duke 已提交
175
#else
176 177
  if(!region_stack()->push(region_index)) {
    region_overflow_stack()->push(region_index);
D
duke 已提交
178 179 180 181
  }
#endif
}

182 183 184
bool ParCompactionManager::retrieve_for_processing(size_t& region_index) {
#ifdef USE_RegionTaskQueueWithOverflow
  return region_stack()->retrieve(region_index);
D
duke 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
#else
  // Should not be used in the parallel case
  ShouldNotReachHere();
  return false;
#endif
}

ParCompactionManager*
ParCompactionManager::gc_thread_compaction_manager(int index) {
  assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
  assert(_manager_array != NULL, "Sanity");
  return _manager_array[index];
}

void ParCompactionManager::reset() {
  for(uint i=0; i<ParallelGCThreads+1; i++) {
    manager_array(i)->revisit_klass_stack()->clear();
Y
ysr 已提交
202
    manager_array(i)->revisit_mdo_stack()->clear();
D
duke 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
  }
}

void ParCompactionManager::drain_marking_stacks(OopClosure* blk) {
#ifdef ASSERT
  ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
  assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
  MutableSpace* to_space = heap->young_gen()->to_space();
  MutableSpace* old_space = heap->old_gen()->object_space();
  MutableSpace* perm_space = heap->perm_gen()->object_space();
#endif /* ASSERT */


  do {

    // Drain overflow stack first, so other threads can steal from
    // claimed stack while we work.
    while(!overflow_stack()->is_empty()) {
      oop obj = overflow_stack()->pop();
      obj->follow_contents(this);
    }

    oop obj;
    // obj is a reference!!!
    while (marking_stack()->pop_local(obj)) {
      // It would be nice to assert about the type of objects we might
      // pop, but they can come from anywhere, unfortunately.
      obj->follow_contents(this);
    }
  } while((marking_stack()->size() != 0) || (overflow_stack()->length() != 0));

  assert(marking_stack()->size() == 0, "Sanity");
  assert(overflow_stack()->length() == 0, "Sanity");
}

238 239 240 241
void ParCompactionManager::drain_region_overflow_stack() {
  size_t region_index = (size_t) -1;
  while(region_stack()->retrieve_from_overflow(region_index)) {
    PSParallelCompact::fill_and_update_region(this, region_index);
D
duke 已提交
242 243 244
  }
}

245
void ParCompactionManager::drain_region_stacks() {
D
duke 已提交
246 247 248 249 250 251 252 253 254 255 256
#ifdef ASSERT
  ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
  assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
  MutableSpace* to_space = heap->young_gen()->to_space();
  MutableSpace* old_space = heap->old_gen()->object_space();
  MutableSpace* perm_space = heap->perm_gen()->object_space();
#endif /* ASSERT */

#if 1 // def DO_PARALLEL - the serial code hasn't been updated
  do {

257
#ifdef USE_RegionTaskQueueWithOverflow
D
duke 已提交
258 259
    // Drain overflow stack first, so other threads can steal from
    // claimed stack while we work.
260 261 262
    size_t region_index = (size_t) -1;
    while(region_stack()->retrieve_from_overflow(region_index)) {
      PSParallelCompact::fill_and_update_region(this, region_index);
D
duke 已提交
263 264
    }

265 266
    while (region_stack()->retrieve_from_stealable_queue(region_index)) {
      PSParallelCompact::fill_and_update_region(this, region_index);
D
duke 已提交
267
    }
268
  } while (!region_stack()->is_empty());
D
duke 已提交
269 270 271
#else
    // Drain overflow stack first, so other threads can steal from
    // claimed stack while we work.
272 273 274
    while(!region_overflow_stack()->is_empty()) {
      size_t region_index = region_overflow_stack()->pop();
      PSParallelCompact::fill_and_update_region(this, region_index);
D
duke 已提交
275 276
    }

277
    size_t region_index = -1;
D
duke 已提交
278
    // obj is a reference!!!
279
    while (region_stack()->pop_local(region_index)) {
D
duke 已提交
280 281
      // It would be nice to assert about the type of objects we might
      // pop, but they can come from anywhere, unfortunately.
282
      PSParallelCompact::fill_and_update_region(this, region_index);
D
duke 已提交
283
    }
284 285
  } while((region_stack()->size() != 0) ||
          (region_overflow_stack()->length() != 0));
D
duke 已提交
286 287
#endif

288 289
#ifdef USE_RegionTaskQueueWithOverflow
  assert(region_stack()->is_empty(), "Sanity");
D
duke 已提交
290
#else
291 292
  assert(region_stack()->size() == 0, "Sanity");
  assert(region_overflow_stack()->length() == 0, "Sanity");
D
duke 已提交
293 294 295 296 297 298 299 300 301 302 303
#endif
#else
  oop obj;
  while (obj = retrieve_for_scanning()) {
    obj->follow_contents(this);
  }
#endif
}

#ifdef ASSERT
bool ParCompactionManager::stacks_have_been_allocated() {
Y
ysr 已提交
304 305
  return (revisit_klass_stack()->data_addr() != NULL &&
          revisit_mdo_stack()->data_addr() != NULL);
D
duke 已提交
306 307
}
#endif