1 #ifdef USE_PRAGMA_IDENT_SRC 2 #pragma ident "@(#)pcTasks.cpp 1.22 07/06/22 16:49:49 JVM" 3 #endif 4 /* 5 * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. 6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 * 8 * This code is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 only, as 10 * published by the Free Software Foundation. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 23 * CA 95054 USA or visit www.sun.com if you need additional information or 24 * have any questions. 25 * 26 */ 27 28 # include "incls/_precompiled.incl" 29 # include "incls/_pcTasks.cpp.incl" 30 31 // 32 // ThreadRootsMarkingTask 33 // 34 35 void ThreadRootsMarkingTask::do_it(GCTaskManager* manager, uint which) { 36 assert(Universe::heap()->is_gc_active(), "called outside gc"); 37 38 ResourceMark rm; 39 40 NOT_PRODUCT(TraceTime tm("ThreadRootsMarkingTask", 41 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 42 ParCompactionManager* cm = 43 ParCompactionManager::gc_thread_compaction_manager(which); 44 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); 45 46 if (_java_thread != NULL) 47 _java_thread->oops_do(&mark_and_push_closure); 48 49 if (_vm_thread != NULL) 50 _vm_thread->oops_do(&mark_and_push_closure); 51 52 // Do the real work 53 cm->drain_marking_stacks(&mark_and_push_closure); 54 } 55 56 57 void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) { 58 assert(Universe::heap()->is_gc_active(), "called outside gc"); 59 60 NOT_PRODUCT(TraceTime tm("MarkFromRootsTask", 61 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 62 ParCompactionManager* cm = 63 ParCompactionManager::gc_thread_compaction_manager(which); 64 // cm->allocate_stacks(); 65 assert(cm->stacks_have_been_allocated(), 66 "Stack space has not been allocated"); 67 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); 68 69 switch (_root_type) { 70 case universe: 71 Universe::oops_do(&mark_and_push_closure); 72 break; 73 74 case reference_processing: 75 ReferenceProcessor::oops_do(&mark_and_push_closure); 76 break; 77 78 case jni_handles: 79 JNIHandles::oops_do(&mark_and_push_closure); 80 break; 81 82 case threads: 83 { 84 ResourceMark rm; 85 Threads::oops_do(&mark_and_push_closure); 86 } 87 break; 88 89 case object_synchronizer: 90 ObjectSynchronizer::oops_do(&mark_and_push_closure); 91 break; 92 93 case flat_profiler: 94 FlatProfiler::oops_do(&mark_and_push_closure); 95 break; 96 97 case management: 98 Management::oops_do(&mark_and_push_closure); 99 break; 100 101 case jvmti: 102 JvmtiExport::oops_do(&mark_and_push_closure); 103 break; 104 105 case system_dictionary: 106 SystemDictionary::always_strong_oops_do(&mark_and_push_closure); 107 break; 108 109 case vm_symbols: 110 vmSymbols::oops_do(&mark_and_push_closure); 111 break; 112 113 default: 114 fatal("Unknown root type"); 115 } 116 117 // Do the real work 118 cm->drain_marking_stacks(&mark_and_push_closure); 119 // cm->deallocate_stacks(); 120 } 121 122 123 // 124 // RefProcTaskProxy 125 // 126 127 void RefProcTaskProxy::do_it(GCTaskManager* manager, uint which) 128 { 129 assert(Universe::heap()->is_gc_active(), "called outside gc"); 130 131 NOT_PRODUCT(TraceTime tm("RefProcTask", 132 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 133 ParCompactionManager* cm = 134 ParCompactionManager::gc_thread_compaction_manager(which); 135 // cm->allocate_stacks(); 136 assert(cm->stacks_have_been_allocated(), 137 "Stack space has not been allocated"); 138 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); 139 PSParallelCompact::FollowStackClosure follow_stack_closure(cm); 140 _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(), 141 mark_and_push_closure, follow_stack_closure); 142 } 143 144 // 145 // RefProcTaskExecutor 146 // 147 148 void RefProcTaskExecutor::execute(ProcessTask& task) 149 { 150 ParallelScavengeHeap* heap = PSParallelCompact::gc_heap(); 151 uint parallel_gc_threads = heap->gc_task_manager()->workers(); 152 TaskQueueSetSuper* qset = ParCompactionManager::chunk_array(); 153 ParallelTaskTerminator terminator(parallel_gc_threads, qset); 154 GCTaskQueue* q = GCTaskQueue::create(); 155 for(uint i=0; i<parallel_gc_threads; i++) { 156 q->enqueue(new RefProcTaskProxy(task, i)); 157 } 158 if (task.marks_oops_alive()) { 159 if (parallel_gc_threads>1) { 160 for (uint j=0; j<parallel_gc_threads; j++) { 161 q->enqueue(new StealMarkingTask(&terminator)); 162 } 163 } 164 } 165 PSParallelCompact::gc_task_manager()->execute_and_wait(q); 166 } 167 168 void RefProcTaskExecutor::execute(EnqueueTask& task) 169 { 170 ParallelScavengeHeap* heap = PSParallelCompact::gc_heap(); 171 uint parallel_gc_threads = heap->gc_task_manager()->workers(); 172 GCTaskQueue* q = GCTaskQueue::create(); 173 for(uint i=0; i<parallel_gc_threads; i++) { 174 q->enqueue(new RefEnqueueTaskProxy(task, i)); 175 } 176 PSParallelCompact::gc_task_manager()->execute_and_wait(q); 177 } 178 179 // 180 // StealMarkingTask 181 // 182 183 StealMarkingTask::StealMarkingTask(ParallelTaskTerminator* t) : 184 _terminator(t) {} 185 186 void StealMarkingTask::do_it(GCTaskManager* manager, uint which) { 187 assert(Universe::heap()->is_gc_active(), "called outside gc"); 188 189 NOT_PRODUCT(TraceTime tm("StealMarkingTask", 190 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 191 192 ParCompactionManager* cm = 193 ParCompactionManager::gc_thread_compaction_manager(which); 194 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); 195 196 oop obj = NULL; 197 int random_seed = 17; 198 while(true) { 199 if (ParCompactionManager::steal(which, &random_seed, obj)) { 200 obj->follow_contents(cm); 201 cm->drain_marking_stacks(&mark_and_push_closure); 202 } else { 203 if (terminator()->offer_termination()) { 204 break; 205 } 206 } 207 } 208 } 209 210 // 211 // StealChunkCompactionTask 212 // 213 214 215 StealChunkCompactionTask::StealChunkCompactionTask(ParallelTaskTerminator* t) : 216 _terminator(t) {}; 217 218 void StealChunkCompactionTask::do_it(GCTaskManager* manager, uint which) { 219 assert(Universe::heap()->is_gc_active(), "called outside gc"); 220 221 NOT_PRODUCT(TraceTime tm("StealChunkCompactionTask", 222 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 223 224 ParCompactionManager* cm = 225 ParCompactionManager::gc_thread_compaction_manager(which); 226 227 // Has to drain stacks first because there may be chunks on 228 // preloaded onto the stack and this thread may never have 229 // done a draining task. Are the draining tasks needed? 230 231 cm->drain_chunk_stacks(); 232 233 size_t chunk_index = 0; 234 int random_seed = 17; 235 236 // If we're the termination task, try 10 rounds of stealing before 237 // setting the termination flag 238 239 while(true) { 240 if (ParCompactionManager::steal(which, &random_seed, chunk_index)) { 241 PSParallelCompact::fill_and_update_chunk(cm, chunk_index); 242 cm->drain_chunk_stacks(); 243 } else { 244 if (terminator()->offer_termination()) { 245 break; 246 } 247 // Go around again. 248 } 249 } 250 return; 251 } 252 253 UpdateDensePrefixTask::UpdateDensePrefixTask( 254 PSParallelCompact::SpaceId space_id, 255 size_t chunk_index_start, 256 size_t chunk_index_end) : 257 _space_id(space_id), _chunk_index_start(chunk_index_start), 258 _chunk_index_end(chunk_index_end) 259 {} 260 261 void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) { 262 263 NOT_PRODUCT(TraceTime tm("UpdateDensePrefixTask", 264 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 265 266 ParCompactionManager* cm = 267 ParCompactionManager::gc_thread_compaction_manager(which); 268 269 PSParallelCompact::update_and_deadwood_in_dense_prefix(cm, 270 _space_id, 271 _chunk_index_start, 272 _chunk_index_end); 273 } 274 275 void DrainStacksCompactionTask::do_it(GCTaskManager* manager, uint which) { 276 assert(Universe::heap()->is_gc_active(), "called outside gc"); 277 278 NOT_PRODUCT(TraceTime tm("DrainStacksCompactionTask", 279 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 280 281 ParCompactionManager* cm = 282 ParCompactionManager::gc_thread_compaction_manager(which); 283 284 // Process any chunks already in the compaction managers stacks. 285 cm->drain_chunk_stacks(); 286 } 287