src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp

Thu, 27 May 2010 19:08:38 -0700

author
trims
date
Thu, 27 May 2010 19:08:38 -0700
changeset 1907
c18cbe5936b8
parent 1750
c385bf94cfb8
child 1993
b2a00dd3117c
permissions
-rw-r--r--

6941466: Oracle rebranding changes for Hotspot repositories
Summary: Change all the Sun copyrights to Oracle copyright
Reviewed-by: ohair

     1 /*
     2  * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "incls/_precompiled.incl"
    26 #include "incls/_psCompactionManager.cpp.incl"
    28 PSOldGen*            ParCompactionManager::_old_gen = NULL;
    29 ParCompactionManager**  ParCompactionManager::_manager_array = NULL;
    30 OopTaskQueueSet*     ParCompactionManager::_stack_array = NULL;
    31 ParCompactionManager::ObjArrayTaskQueueSet*
    32   ParCompactionManager::_objarray_queues = NULL;
    33 ObjectStartArray*    ParCompactionManager::_start_array = NULL;
    34 ParMarkBitMap*       ParCompactionManager::_mark_bitmap = NULL;
    35 RegionTaskQueueSet*   ParCompactionManager::_region_array = NULL;
    37 ParCompactionManager::ParCompactionManager() :
    38     _action(CopyAndUpdate) {
    40   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
    41   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
    43   _old_gen = heap->old_gen();
    44   _start_array = old_gen()->start_array();
    47   marking_stack()->initialize();
    49   // We want the overflow stack to be permanent
    50   _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
    52   _objarray_queue.initialize();
    53   _objarray_overflow_stack =
    54     new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true);
    56 #ifdef USE_RegionTaskQueueWithOverflow
    57   region_stack()->initialize();
    58 #else
    59   region_stack()->initialize();
    61   // We want the overflow stack to be permanent
    62   _region_overflow_stack =
    63     new (ResourceObj::C_HEAP) GrowableArray<size_t>(10, true);
    64 #endif
    66   // Note that _revisit_klass_stack is allocated out of the
    67   // C heap (as opposed to out of ResourceArena).
    68   int size =
    69     (SystemDictionary::number_of_classes() * 2) * 2 / ParallelGCThreads;
    70   _revisit_klass_stack = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(size, true);
    71   // From some experiments (#klass/k)^2 for k = 10 seems a better fit, but this will
    72   // have to do for now until we are able to investigate a more optimal setting.
    73   _revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true);
    75 }
    77 ParCompactionManager::~ParCompactionManager() {
    78   delete _overflow_stack;
    79   delete _objarray_overflow_stack;
    80   delete _revisit_klass_stack;
    81   delete _revisit_mdo_stack;
    82   // _manager_array and _stack_array are statics
    83   // shared with all instances of ParCompactionManager
    84   // should not be deallocated.
    85 }
    87 void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
    88   assert(PSParallelCompact::gc_task_manager() != NULL,
    89     "Needed for initialization");
    91   _mark_bitmap = mbm;
    93   uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();
    95   assert(_manager_array == NULL, "Attempt to initialize twice");
    96   _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 );
    97   guarantee(_manager_array != NULL, "Could not allocate manager_array");
    99   _stack_array = new OopTaskQueueSet(parallel_gc_threads);
   100   guarantee(_stack_array != NULL, "Could not allocate stack_array");
   101   _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads);
   102   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");
   106   // Create and register the ParCompactionManager(s) for the worker threads.
   107   for(uint i=0; i<parallel_gc_threads; i++) {
   108     _manager_array[i] = new ParCompactionManager();
   109     guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");
   110     stack_array()->register_queue(i, _manager_array[i]->marking_stack());
   111     _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue);
   112 #ifdef USE_RegionTaskQueueWithOverflow
   113     region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue());
   114 #else
   115     region_array()->register_queue(i, _manager_array[i]->region_stack());
   116 #endif
   117   }
   119   // The VMThread gets its own ParCompactionManager, which is not available
   120   // for work stealing.
   121   _manager_array[parallel_gc_threads] = new ParCompactionManager();
   122   guarantee(_manager_array[parallel_gc_threads] != NULL,
   123     "Could not create ParCompactionManager");
   124   assert(PSParallelCompact::gc_task_manager()->workers() != 0,
   125     "Not initialized?");
   126 }
   128 bool ParCompactionManager::should_update() {
   129   assert(action() != NotValid, "Action is not set");
   130   return (action() == ParCompactionManager::Update) ||
   131          (action() == ParCompactionManager::CopyAndUpdate) ||
   132          (action() == ParCompactionManager::UpdateAndCopy);
   133 }
   135 bool ParCompactionManager::should_copy() {
   136   assert(action() != NotValid, "Action is not set");
   137   return (action() == ParCompactionManager::Copy) ||
   138          (action() == ParCompactionManager::CopyAndUpdate) ||
   139          (action() == ParCompactionManager::UpdateAndCopy);
   140 }
   142 bool ParCompactionManager::should_verify_only() {
   143   assert(action() != NotValid, "Action is not set");
   144   return action() == ParCompactionManager::VerifyUpdate;
   145 }
   147 bool ParCompactionManager::should_reset_only() {
   148   assert(action() != NotValid, "Action is not set");
   149   return action() == ParCompactionManager::ResetObjects;
   150 }
   152 // For now save on a stack
   153 void ParCompactionManager::save_for_scanning(oop m) {
   154   stack_push(m);
   155 }
   157 void ParCompactionManager::stack_push(oop obj) {
   159   if(!marking_stack()->push(obj)) {
   160     overflow_stack()->push(obj);
   161   }
   162 }
   164 oop ParCompactionManager::retrieve_for_scanning() {
   166   // Should not be used in the parallel case
   167   ShouldNotReachHere();
   168   return NULL;
   169 }
   171 // Save region on a stack
   172 void ParCompactionManager::save_for_processing(size_t region_index) {
   173 #ifdef ASSERT
   174   const ParallelCompactData& sd = PSParallelCompact::summary_data();
   175   ParallelCompactData::RegionData* const region_ptr = sd.region(region_index);
   176   assert(region_ptr->claimed(), "must be claimed");
   177   assert(region_ptr->_pushed++ == 0, "should only be pushed once");
   178 #endif
   179   region_stack_push(region_index);
   180 }
   182 void ParCompactionManager::region_stack_push(size_t region_index) {
   184 #ifdef USE_RegionTaskQueueWithOverflow
   185   region_stack()->save(region_index);
   186 #else
   187   if(!region_stack()->push(region_index)) {
   188     region_overflow_stack()->push(region_index);
   189   }
   190 #endif
   191 }
   193 bool ParCompactionManager::retrieve_for_processing(size_t& region_index) {
   194 #ifdef USE_RegionTaskQueueWithOverflow
   195   return region_stack()->retrieve(region_index);
   196 #else
   197   // Should not be used in the parallel case
   198   ShouldNotReachHere();
   199   return false;
   200 #endif
   201 }
   203 ParCompactionManager*
   204 ParCompactionManager::gc_thread_compaction_manager(int index) {
   205   assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
   206   assert(_manager_array != NULL, "Sanity");
   207   return _manager_array[index];
   208 }
   210 void ParCompactionManager::reset() {
   211   for(uint i=0; i<ParallelGCThreads+1; i++) {
   212     manager_array(i)->revisit_klass_stack()->clear();
   213     manager_array(i)->revisit_mdo_stack()->clear();
   214   }
   215 }
   217 void ParCompactionManager::follow_marking_stacks() {
   218   do {
   219     // Drain the overflow stack first, to allow stealing from the marking stack.
   220     oop obj;
   221     while (!overflow_stack()->is_empty()) {
   222       overflow_stack()->pop()->follow_contents(this);
   223     }
   224     while (marking_stack()->pop_local(obj)) {
   225       obj->follow_contents(this);
   226     }
   228     // Process ObjArrays one at a time to avoid marking stack bloat.
   229     ObjArrayTask task;
   230     if (!_objarray_overflow_stack->is_empty()) {
   231       task = _objarray_overflow_stack->pop();
   232       objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
   233       k->oop_follow_contents(this, task.obj(), task.index());
   234     } else if (_objarray_queue.pop_local(task)) {
   235       objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
   236       k->oop_follow_contents(this, task.obj(), task.index());
   237     }
   238   } while (!marking_stacks_empty());
   240   assert(marking_stacks_empty(), "Sanity");
   241 }
   243 void ParCompactionManager::drain_region_overflow_stack() {
   244   size_t region_index = (size_t) -1;
   245   while(region_stack()->retrieve_from_overflow(region_index)) {
   246     PSParallelCompact::fill_and_update_region(this, region_index);
   247   }
   248 }
   250 void ParCompactionManager::drain_region_stacks() {
   251 #ifdef ASSERT
   252   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   253   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
   254   MutableSpace* to_space = heap->young_gen()->to_space();
   255   MutableSpace* old_space = heap->old_gen()->object_space();
   256   MutableSpace* perm_space = heap->perm_gen()->object_space();
   257 #endif /* ASSERT */
   259 #if 1 // def DO_PARALLEL - the serial code hasn't been updated
   260   do {
   262 #ifdef USE_RegionTaskQueueWithOverflow
   263     // Drain overflow stack first, so other threads can steal from
   264     // claimed stack while we work.
   265     size_t region_index = (size_t) -1;
   266     while(region_stack()->retrieve_from_overflow(region_index)) {
   267       PSParallelCompact::fill_and_update_region(this, region_index);
   268     }
   270     while (region_stack()->retrieve_from_stealable_queue(region_index)) {
   271       PSParallelCompact::fill_and_update_region(this, region_index);
   272     }
   273   } while (!region_stack()->is_empty());
   274 #else
   275     // Drain overflow stack first, so other threads can steal from
   276     // claimed stack while we work.
   277     while(!region_overflow_stack()->is_empty()) {
   278       size_t region_index = region_overflow_stack()->pop();
   279       PSParallelCompact::fill_and_update_region(this, region_index);
   280     }
   282     size_t region_index = -1;
   283     // obj is a reference!!!
   284     while (region_stack()->pop_local(region_index)) {
   285       // It would be nice to assert about the type of objects we might
   286       // pop, but they can come from anywhere, unfortunately.
   287       PSParallelCompact::fill_and_update_region(this, region_index);
   288     }
   289   } while((region_stack()->size() != 0) ||
   290           (region_overflow_stack()->length() != 0));
   291 #endif
   293 #ifdef USE_RegionTaskQueueWithOverflow
   294   assert(region_stack()->is_empty(), "Sanity");
   295 #else
   296   assert(region_stack()->size() == 0, "Sanity");
   297   assert(region_overflow_stack()->length() == 0, "Sanity");
   298 #endif
   299 #else
   300   oop obj;
   301   while (obj = retrieve_for_scanning()) {
   302     obj->follow_contents(this);
   303   }
   304 #endif
   305 }
   307 #ifdef ASSERT
   308 bool ParCompactionManager::stacks_have_been_allocated() {
   309   return (revisit_klass_stack()->data_addr() != NULL &&
   310           revisit_mdo_stack()->data_addr() != NULL);
   311 }
   312 #endif

mercurial