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-2008 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 RegionTaskQueueSet* qset = ParCompactionManager::region_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 // StealRegionCompactionTask 212 // 213 214 215 StealRegionCompactionTask::StealRegionCompactionTask(ParallelTaskTerminator* t): 216 _terminator(t) {} 217 218 void StealRegionCompactionTask::do_it(GCTaskManager* manager, uint which) { 219 assert(Universe::heap()->is_gc_active(), "called outside gc"); 220 221 NOT_PRODUCT(TraceTime tm("StealRegionCompactionTask", 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 regions 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_region_stacks(); 232 233 size_t region_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, region_index)) { 241 PSParallelCompact::fill_and_update_region(cm, region_index); 242 cm->drain_region_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 region_index_start, 256 size_t region_index_end) : 257 _space_id(space_id), _region_index_start(region_index_start), 258 _region_index_end(region_index_end) {} 259 260 void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) { 261 262 NOT_PRODUCT(TraceTime tm("UpdateDensePrefixTask", 263 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 264 265 ParCompactionManager* cm = 266 ParCompactionManager::gc_thread_compaction_manager(which); 267 268 PSParallelCompact::update_and_deadwood_in_dense_prefix(cm, 269 _space_id, 270 _region_index_start, 271 _region_index_end); 272 } 273 274 void DrainStacksCompactionTask::do_it(GCTaskManager* manager, uint which) { 275 assert(Universe::heap()->is_gc_active(), "called outside gc"); 276 277 NOT_PRODUCT(TraceTime tm("DrainStacksCompactionTask", 278 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 279 280 ParCompactionManager* cm = 281 ParCompactionManager::gc_thread_compaction_manager(which); 282 283 // Process any regions already in the compaction managers stacks. 284 cm->drain_region_stacks(); 285 } 286