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

Thu, 22 Sep 2011 10:57:37 -0700

author
johnc
date
Thu, 22 Sep 2011 10:57:37 -0700
changeset 3175
4dfb2df418f2
parent 2314
f95d63e2154a
child 3294
bca17e38de00
permissions
-rw-r--r--

6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp

duke@435 1 /*
jcoomes@1993 2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "classfile/systemDictionary.hpp"
stefank@2314 27 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
stefank@2314 28 #include "gc_implementation/parallelScavenge/objectStartArray.hpp"
stefank@2314 29 #include "gc_implementation/parallelScavenge/parMarkBitMap.hpp"
stefank@2314 30 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
stefank@2314 31 #include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
stefank@2314 32 #include "gc_implementation/parallelScavenge/psOldGen.hpp"
stefank@2314 33 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
stefank@2314 34 #include "oops/objArrayKlass.inline.hpp"
stefank@2314 35 #include "oops/oop.hpp"
stefank@2314 36 #include "oops/oop.inline.hpp"
stefank@2314 37 #include "oops/oop.pcgc.inline.hpp"
stefank@2314 38 #include "utilities/stack.inline.hpp"
duke@435 39
duke@435 40 PSOldGen* ParCompactionManager::_old_gen = NULL;
duke@435 41 ParCompactionManager** ParCompactionManager::_manager_array = NULL;
duke@435 42 OopTaskQueueSet* ParCompactionManager::_stack_array = NULL;
jcoomes@1746 43 ParCompactionManager::ObjArrayTaskQueueSet*
jcoomes@1746 44 ParCompactionManager::_objarray_queues = NULL;
duke@435 45 ObjectStartArray* ParCompactionManager::_start_array = NULL;
duke@435 46 ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL;
jcoomes@1993 47 RegionTaskQueueSet* ParCompactionManager::_region_array = NULL;
duke@435 48
duke@435 49 ParCompactionManager::ParCompactionManager() :
duke@435 50 _action(CopyAndUpdate) {
duke@435 51
duke@435 52 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
duke@435 53 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
duke@435 54
duke@435 55 _old_gen = heap->old_gen();
duke@435 56 _start_array = old_gen()->start_array();
duke@435 57
duke@435 58 marking_stack()->initialize();
jcoomes@1993 59 _objarray_stack.initialize();
jcoomes@810 60 region_stack()->initialize();
duke@435 61 }
duke@435 62
duke@435 63 void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
duke@435 64 assert(PSParallelCompact::gc_task_manager() != NULL,
duke@435 65 "Needed for initialization");
duke@435 66
duke@435 67 _mark_bitmap = mbm;
duke@435 68
duke@435 69 uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();
duke@435 70
duke@435 71 assert(_manager_array == NULL, "Attempt to initialize twice");
duke@435 72 _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 );
jcoomes@1746 73 guarantee(_manager_array != NULL, "Could not allocate manager_array");
duke@435 74
duke@435 75 _stack_array = new OopTaskQueueSet(parallel_gc_threads);
jcoomes@1746 76 guarantee(_stack_array != NULL, "Could not allocate stack_array");
jcoomes@1746 77 _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads);
jcoomes@1746 78 guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues");
jcoomes@810 79 _region_array = new RegionTaskQueueSet(parallel_gc_threads);
jcoomes@1746 80 guarantee(_region_array != NULL, "Could not allocate region_array");
duke@435 81
duke@435 82 // Create and register the ParCompactionManager(s) for the worker threads.
duke@435 83 for(uint i=0; i<parallel_gc_threads; i++) {
duke@435 84 _manager_array[i] = new ParCompactionManager();
duke@435 85 guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");
duke@435 86 stack_array()->register_queue(i, _manager_array[i]->marking_stack());
jcoomes@1993 87 _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack);
jcoomes@810 88 region_array()->register_queue(i, _manager_array[i]->region_stack());
duke@435 89 }
duke@435 90
duke@435 91 // The VMThread gets its own ParCompactionManager, which is not available
duke@435 92 // for work stealing.
duke@435 93 _manager_array[parallel_gc_threads] = new ParCompactionManager();
duke@435 94 guarantee(_manager_array[parallel_gc_threads] != NULL,
duke@435 95 "Could not create ParCompactionManager");
duke@435 96 assert(PSParallelCompact::gc_task_manager()->workers() != 0,
duke@435 97 "Not initialized?");
duke@435 98 }
duke@435 99
duke@435 100 bool ParCompactionManager::should_update() {
duke@435 101 assert(action() != NotValid, "Action is not set");
duke@435 102 return (action() == ParCompactionManager::Update) ||
duke@435 103 (action() == ParCompactionManager::CopyAndUpdate) ||
duke@435 104 (action() == ParCompactionManager::UpdateAndCopy);
duke@435 105 }
duke@435 106
duke@435 107 bool ParCompactionManager::should_copy() {
duke@435 108 assert(action() != NotValid, "Action is not set");
duke@435 109 return (action() == ParCompactionManager::Copy) ||
duke@435 110 (action() == ParCompactionManager::CopyAndUpdate) ||
duke@435 111 (action() == ParCompactionManager::UpdateAndCopy);
duke@435 112 }
duke@435 113
duke@435 114 bool ParCompactionManager::should_verify_only() {
duke@435 115 assert(action() != NotValid, "Action is not set");
duke@435 116 return action() == ParCompactionManager::VerifyUpdate;
duke@435 117 }
duke@435 118
duke@435 119 bool ParCompactionManager::should_reset_only() {
duke@435 120 assert(action() != NotValid, "Action is not set");
duke@435 121 return action() == ParCompactionManager::ResetObjects;
duke@435 122 }
duke@435 123
duke@435 124 ParCompactionManager*
duke@435 125 ParCompactionManager::gc_thread_compaction_manager(int index) {
duke@435 126 assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
duke@435 127 assert(_manager_array != NULL, "Sanity");
duke@435 128 return _manager_array[index];
duke@435 129 }
duke@435 130
duke@435 131 void ParCompactionManager::reset() {
jcoomes@2191 132 for(uint i = 0; i < ParallelGCThreads + 1; i++) {
jcoomes@2191 133 assert(manager_array(i)->revisit_klass_stack()->is_empty(), "sanity");
jcoomes@2191 134 assert(manager_array(i)->revisit_mdo_stack()->is_empty(), "sanity");
duke@435 135 }
duke@435 136 }
duke@435 137
jcoomes@1746 138 void ParCompactionManager::follow_marking_stacks() {
duke@435 139 do {
jcoomes@1746 140 // Drain the overflow stack first, to allow stealing from the marking stack.
jcoomes@1750 141 oop obj;
jcoomes@1993 142 while (marking_stack()->pop_overflow(obj)) {
jcoomes@1993 143 obj->follow_contents(this);
jcoomes@1746 144 }
jcoomes@1746 145 while (marking_stack()->pop_local(obj)) {
duke@435 146 obj->follow_contents(this);
duke@435 147 }
duke@435 148
jcoomes@1750 149 // Process ObjArrays one at a time to avoid marking stack bloat.
jcoomes@1746 150 ObjArrayTask task;
jcoomes@1993 151 if (_objarray_stack.pop_overflow(task)) {
jcoomes@1746 152 objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
jcoomes@1746 153 k->oop_follow_contents(this, task.obj(), task.index());
jcoomes@1993 154 } else if (_objarray_stack.pop_local(task)) {
jcoomes@1746 155 objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
jcoomes@1746 156 k->oop_follow_contents(this, task.obj(), task.index());
jcoomes@1746 157 }
jcoomes@1746 158 } while (!marking_stacks_empty());
duke@435 159
jcoomes@1746 160 assert(marking_stacks_empty(), "Sanity");
duke@435 161 }
duke@435 162
jcoomes@810 163 void ParCompactionManager::drain_region_stacks() {
duke@435 164 do {
jcoomes@1993 165 // Drain overflow stack first so other threads can steal.
jcoomes@1993 166 size_t region_index;
jcoomes@1993 167 while (region_stack()->pop_overflow(region_index)) {
jcoomes@810 168 PSParallelCompact::fill_and_update_region(this, region_index);
duke@435 169 }
duke@435 170
jcoomes@1993 171 while (region_stack()->pop_local(region_index)) {
jcoomes@810 172 PSParallelCompact::fill_and_update_region(this, region_index);
duke@435 173 }
jcoomes@810 174 } while (!region_stack()->is_empty());
duke@435 175 }

mercurial