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