psCompactionManager.cpp 11.0 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * 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.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24 25 26 27 28 29 30
 *
 */

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

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

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);
51 52 53 54 55

  _objarray_queue.initialize();
  _objarray_overflow_stack =
    new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true);

56 57
#ifdef USE_RegionTaskQueueWithOverflow
  region_stack()->initialize();
D
duke 已提交
58
#else
59
  region_stack()->initialize();
D
duke 已提交
60 61

  // We want the overflow stack to be permanent
62
  _region_overflow_stack =
D
duke 已提交
63 64 65 66 67 68 69 70
    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 已提交
71 72 73
  // 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 已提交
74 75 76 77 78

}

ParCompactionManager::~ParCompactionManager() {
  delete _overflow_stack;
79
  delete _objarray_overflow_stack;
D
duke 已提交
80
  delete _revisit_klass_stack;
Y
ysr 已提交
81
  delete _revisit_mdo_stack;
D
duke 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
  // _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 );
97
  guarantee(_manager_array != NULL, "Could not allocate manager_array");
D
duke 已提交
98 99

  _stack_array = new OopTaskQueueSet(parallel_gc_threads);
100 101 102
  guarantee(_stack_array != NULL, "Could not allocate stack_array");
  _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads);
  guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues");
103
  _region_array = new RegionTaskQueueSet(parallel_gc_threads);
104
  guarantee(_region_array != NULL, "Could not allocate region_array");
D
duke 已提交
105 106 107 108 109 110

  // 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());
111
    _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue);
112 113
#ifdef USE_RegionTaskQueueWithOverflow
    region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue());
D
duke 已提交
114
#else
115
    region_array()->register_queue(i, _manager_array[i]->region_stack());
D
duke 已提交
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 160 161 162 163 164 165 166 167 168 169 170
#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;
}

171 172
// Save region on a stack
void ParCompactionManager::save_for_processing(size_t region_index) {
D
duke 已提交
173 174
#ifdef ASSERT
  const ParallelCompactData& sd = PSParallelCompact::summary_data();
175 176 177
  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 已提交
178
#endif
179
  region_stack_push(region_index);
D
duke 已提交
180 181
}

182
void ParCompactionManager::region_stack_push(size_t region_index) {
D
duke 已提交
183

184 185
#ifdef USE_RegionTaskQueueWithOverflow
  region_stack()->save(region_index);
D
duke 已提交
186
#else
187 188
  if(!region_stack()->push(region_index)) {
    region_overflow_stack()->push(region_index);
D
duke 已提交
189 190 191 192
  }
#endif
}

193 194 195
bool ParCompactionManager::retrieve_for_processing(size_t& region_index) {
#ifdef USE_RegionTaskQueueWithOverflow
  return region_stack()->retrieve(region_index);
D
duke 已提交
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
#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 已提交
213
    manager_array(i)->revisit_mdo_stack()->clear();
D
duke 已提交
214 215 216
  }
}

217
void ParCompactionManager::follow_marking_stacks() {
D
duke 已提交
218
  do {
219
    // Drain the overflow stack first, to allow stealing from the marking stack.
220
    oop obj;
221 222
    while (!overflow_stack()->is_empty()) {
      overflow_stack()->pop()->follow_contents(this);
D
duke 已提交
223 224 225 226 227
    }
    while (marking_stack()->pop_local(obj)) {
      obj->follow_contents(this);
    }

228
    // Process ObjArrays one at a time to avoid marking stack bloat.
229
    ObjArrayTask task;
230
    if (!_objarray_overflow_stack->is_empty()) {
231 232 233
      task = _objarray_overflow_stack->pop();
      objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
      k->oop_follow_contents(this, task.obj(), task.index());
234
    } else if (_objarray_queue.pop_local(task)) {
235 236 237 238 239 240
      objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
      k->oop_follow_contents(this, task.obj(), task.index());
    }
  } while (!marking_stacks_empty());

  assert(marking_stacks_empty(), "Sanity");
D
duke 已提交
241 242
}

243 244 245 246
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 已提交
247 248 249
  }
}

250
void ParCompactionManager::drain_region_stacks() {
D
duke 已提交
251 252 253 254 255 256 257 258 259 260 261
#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 {

262
#ifdef USE_RegionTaskQueueWithOverflow
D
duke 已提交
263 264
    // Drain overflow stack first, so other threads can steal from
    // claimed stack while we work.
265 266 267
    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 已提交
268 269
    }

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

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

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

#ifdef ASSERT
bool ParCompactionManager::stacks_have_been_allocated() {
Y
ysr 已提交
309 310
  return (revisit_klass_stack()->data_addr() != NULL &&
          revisit_mdo_stack()->data_addr() != NULL);
D
duke 已提交
311 312
}
#endif