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

Tue, 28 Sep 2010 15:56:15 -0700

author
jcoomes
date
Tue, 28 Sep 2010 15:56:15 -0700
changeset 2191
894b1d7c7e01
parent 1993
b2a00dd3117c
child 2314
f95d63e2154a
permissions
-rw-r--r--

6423256: GC stacks should use a better data structure
6942771: SEGV in ParScanThreadState::take_from_overflow_stack
Reviewed-by: apetrusenko, ysr, pbk

     1 /*
     2  * Copyright (c) 2005, 2010, 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();
    46   marking_stack()->initialize();
    47   _objarray_stack.initialize();
    48   region_stack()->initialize();
    49 }
    51 void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
    52   assert(PSParallelCompact::gc_task_manager() != NULL,
    53     "Needed for initialization");
    55   _mark_bitmap = mbm;
    57   uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();
    59   assert(_manager_array == NULL, "Attempt to initialize twice");
    60   _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 );
    61   guarantee(_manager_array != NULL, "Could not allocate manager_array");
    63   _stack_array = new OopTaskQueueSet(parallel_gc_threads);
    64   guarantee(_stack_array != NULL, "Could not allocate stack_array");
    65   _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads);
    66   guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues");
    67   _region_array = new RegionTaskQueueSet(parallel_gc_threads);
    68   guarantee(_region_array != NULL, "Could not allocate region_array");
    70   // Create and register the ParCompactionManager(s) for the worker threads.
    71   for(uint i=0; i<parallel_gc_threads; i++) {
    72     _manager_array[i] = new ParCompactionManager();
    73     guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");
    74     stack_array()->register_queue(i, _manager_array[i]->marking_stack());
    75     _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack);
    76     region_array()->register_queue(i, _manager_array[i]->region_stack());
    77   }
    79   // The VMThread gets its own ParCompactionManager, which is not available
    80   // for work stealing.
    81   _manager_array[parallel_gc_threads] = new ParCompactionManager();
    82   guarantee(_manager_array[parallel_gc_threads] != NULL,
    83     "Could not create ParCompactionManager");
    84   assert(PSParallelCompact::gc_task_manager()->workers() != 0,
    85     "Not initialized?");
    86 }
    88 bool ParCompactionManager::should_update() {
    89   assert(action() != NotValid, "Action is not set");
    90   return (action() == ParCompactionManager::Update) ||
    91          (action() == ParCompactionManager::CopyAndUpdate) ||
    92          (action() == ParCompactionManager::UpdateAndCopy);
    93 }
    95 bool ParCompactionManager::should_copy() {
    96   assert(action() != NotValid, "Action is not set");
    97   return (action() == ParCompactionManager::Copy) ||
    98          (action() == ParCompactionManager::CopyAndUpdate) ||
    99          (action() == ParCompactionManager::UpdateAndCopy);
   100 }
   102 bool ParCompactionManager::should_verify_only() {
   103   assert(action() != NotValid, "Action is not set");
   104   return action() == ParCompactionManager::VerifyUpdate;
   105 }
   107 bool ParCompactionManager::should_reset_only() {
   108   assert(action() != NotValid, "Action is not set");
   109   return action() == ParCompactionManager::ResetObjects;
   110 }
   112 ParCompactionManager*
   113 ParCompactionManager::gc_thread_compaction_manager(int index) {
   114   assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
   115   assert(_manager_array != NULL, "Sanity");
   116   return _manager_array[index];
   117 }
   119 void ParCompactionManager::reset() {
   120   for(uint i = 0; i < ParallelGCThreads + 1; i++) {
   121     assert(manager_array(i)->revisit_klass_stack()->is_empty(), "sanity");
   122     assert(manager_array(i)->revisit_mdo_stack()->is_empty(), "sanity");
   123   }
   124 }
   126 void ParCompactionManager::follow_marking_stacks() {
   127   do {
   128     // Drain the overflow stack first, to allow stealing from the marking stack.
   129     oop obj;
   130     while (marking_stack()->pop_overflow(obj)) {
   131       obj->follow_contents(this);
   132     }
   133     while (marking_stack()->pop_local(obj)) {
   134       obj->follow_contents(this);
   135     }
   137     // Process ObjArrays one at a time to avoid marking stack bloat.
   138     ObjArrayTask task;
   139     if (_objarray_stack.pop_overflow(task)) {
   140       objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
   141       k->oop_follow_contents(this, task.obj(), task.index());
   142     } else if (_objarray_stack.pop_local(task)) {
   143       objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
   144       k->oop_follow_contents(this, task.obj(), task.index());
   145     }
   146   } while (!marking_stacks_empty());
   148   assert(marking_stacks_empty(), "Sanity");
   149 }
   151 void ParCompactionManager::drain_region_stacks() {
   152   do {
   153     // Drain overflow stack first so other threads can steal.
   154     size_t region_index;
   155     while (region_stack()->pop_overflow(region_index)) {
   156       PSParallelCompact::fill_and_update_region(this, region_index);
   157     }
   159     while (region_stack()->pop_local(region_index)) {
   160       PSParallelCompact::fill_and_update_region(this, region_index);
   161     }
   162   } while (!region_stack()->is_empty());
   163 }

mercurial