1 /*
   2  * Copyright (c) 2005, 2009, 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  */
  24 
  25 # include "incls/_precompiled.incl"
  26 # include "incls/_pcTasks.cpp.incl"
  27 
  28 //
  29 // ThreadRootsMarkingTask
  30 //
  31 
  32 void ThreadRootsMarkingTask::do_it(GCTaskManager* manager, uint which) {
  33   assert(Universe::heap()->is_gc_active(), "called outside gc");
  34 
  35   ResourceMark rm;
  36 
  37   NOT_PRODUCT(TraceTime tm("ThreadRootsMarkingTask",
  38     PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
  39   ParCompactionManager* cm =
  40     ParCompactionManager::gc_thread_compaction_manager(which);
  41   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
  42   CodeBlobToOopClosure mark_and_push_in_blobs(&mark_and_push_closure, /*do_marking=*/ true);
  43 
  44   if (_java_thread != NULL)
  45     _java_thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs);
  46 
  47   if (_vm_thread != NULL)
  48     _vm_thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs);
  49 
  50   // Do the real work
  51   cm->follow_marking_stacks();
  52 }
  53 
  54 
  55 void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
  56   assert(Universe::heap()->is_gc_active(), "called outside gc");
  57 
  58   NOT_PRODUCT(TraceTime tm("MarkFromRootsTask",
  59     PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
  60   ParCompactionManager* cm =
  61     ParCompactionManager::gc_thread_compaction_manager(which);
  62   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
  63 
  64   switch (_root_type) {
  65     case universe:
  66       Universe::oops_do(&mark_and_push_closure);
  67       break;
  68 
  69     case reference_processing:
  70       ReferenceProcessor::oops_do(&mark_and_push_closure);
  71       break;
  72 
  73     case jni_handles:
  74       JNIHandles::oops_do(&mark_and_push_closure);
  75       break;
  76 
  77     case threads:
  78     {
  79       ResourceMark rm;
  80       CodeBlobToOopClosure each_active_code_blob(&mark_and_push_closure, /*do_marking=*/ true);
  81       Threads::oops_do(&mark_and_push_closure, &each_active_code_blob);
  82     }
  83     break;
  84 
  85     case object_synchronizer:
  86       ObjectSynchronizer::oops_do(&mark_and_push_closure);
  87       break;
  88 
  89     case flat_profiler:
  90       FlatProfiler::oops_do(&mark_and_push_closure);
  91       break;
  92 
  93     case management:
  94       Management::oops_do(&mark_and_push_closure);
  95       break;
  96 
  97     case jvmti:
  98       JvmtiExport::oops_do(&mark_and_push_closure);
  99       break;
 100 
 101     case system_dictionary:
 102       SystemDictionary::always_strong_oops_do(&mark_and_push_closure);
 103       break;
 104 
 105     case vm_symbols:
 106       vmSymbols::oops_do(&mark_and_push_closure);
 107       break;
 108 
 109     case code_cache:
 110       // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
 111       //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
 112       break;
 113 
 114     default:
 115       fatal("Unknown root type");
 116   }
 117 
 118   // Do the real work
 119   cm->follow_marking_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   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
 136   PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
 137   _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
 138                 mark_and_push_closure, follow_stack_closure);
 139 }
 140 
 141 //
 142 // RefProcTaskExecutor
 143 //
 144 
 145 void RefProcTaskExecutor::execute(ProcessTask& task)
 146 {
 147   ParallelScavengeHeap* heap = PSParallelCompact::gc_heap();
 148   uint parallel_gc_threads = heap->gc_task_manager()->workers();
 149   RegionTaskQueueSet* qset = ParCompactionManager::region_array();
 150   ParallelTaskTerminator terminator(parallel_gc_threads, qset);
 151   GCTaskQueue* q = GCTaskQueue::create();
 152   for(uint i=0; i<parallel_gc_threads; i++) {
 153     q->enqueue(new RefProcTaskProxy(task, i));
 154   }
 155   if (task.marks_oops_alive()) {
 156     if (parallel_gc_threads>1) {
 157       for (uint j=0; j<parallel_gc_threads; j++) {
 158         q->enqueue(new StealMarkingTask(&terminator));
 159       }
 160     }
 161   }
 162   PSParallelCompact::gc_task_manager()->execute_and_wait(q);
 163 }
 164 
 165 void RefProcTaskExecutor::execute(EnqueueTask& task)
 166 {
 167   ParallelScavengeHeap* heap = PSParallelCompact::gc_heap();
 168   uint parallel_gc_threads = heap->gc_task_manager()->workers();
 169   GCTaskQueue* q = GCTaskQueue::create();
 170   for(uint i=0; i<parallel_gc_threads; i++) {
 171     q->enqueue(new RefEnqueueTaskProxy(task, i));
 172   }
 173   PSParallelCompact::gc_task_manager()->execute_and_wait(q);
 174 }
 175 
 176 //
 177 // StealMarkingTask
 178 //
 179 
 180 StealMarkingTask::StealMarkingTask(ParallelTaskTerminator* t) :
 181   _terminator(t) {}
 182 
 183 void StealMarkingTask::do_it(GCTaskManager* manager, uint which) {
 184   assert(Universe::heap()->is_gc_active(), "called outside gc");
 185 
 186   NOT_PRODUCT(TraceTime tm("StealMarkingTask",
 187     PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
 188 
 189   ParCompactionManager* cm =
 190     ParCompactionManager::gc_thread_compaction_manager(which);
 191   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
 192 
 193   oop obj = NULL;
 194   ObjArrayTask task;
 195   int random_seed = 17;
 196   do {
 197     while (ParCompactionManager::steal_objarray(which, &random_seed, task)) {
 198       objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
 199       k->oop_follow_contents(cm, task.obj(), task.index());
 200       cm->follow_marking_stacks();
 201     }
 202     while (ParCompactionManager::steal(which, &random_seed, obj)) {
 203       obj->follow_contents(cm);
 204       cm->follow_marking_stacks();
 205     }
 206   } while (!terminator()->offer_termination());
 207 }
 208 
 209 //
 210 // StealRegionCompactionTask
 211 //
 212 
 213 
 214 StealRegionCompactionTask::StealRegionCompactionTask(ParallelTaskTerminator* t):
 215   _terminator(t) {}
 216 
 217 void StealRegionCompactionTask::do_it(GCTaskManager* manager, uint which) {
 218   assert(Universe::heap()->is_gc_active(), "called outside gc");
 219 
 220   NOT_PRODUCT(TraceTime tm("StealRegionCompactionTask",
 221     PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
 222 
 223   ParCompactionManager* cm =
 224     ParCompactionManager::gc_thread_compaction_manager(which);
 225 
 226   // Has to drain stacks first because there may be regions on
 227   // preloaded onto the stack and this thread may never have
 228   // done a draining task.  Are the draining tasks needed?
 229 
 230   cm->drain_region_stacks();
 231 
 232   size_t region_index = 0;
 233   int random_seed = 17;
 234 
 235   // If we're the termination task, try 10 rounds of stealing before
 236   // setting the termination flag
 237 
 238   while(true) {
 239     if (ParCompactionManager::steal(which, &random_seed, region_index)) {
 240       PSParallelCompact::fill_and_update_region(cm, region_index);
 241       cm->drain_region_stacks();
 242     } else {
 243       if (terminator()->offer_termination()) {
 244         break;
 245       }
 246       // Go around again.
 247     }
 248   }
 249   return;
 250 }
 251 
 252 UpdateDensePrefixTask::UpdateDensePrefixTask(
 253                                    PSParallelCompact::SpaceId space_id,
 254                                    size_t region_index_start,
 255                                    size_t region_index_end) :
 256   _space_id(space_id), _region_index_start(region_index_start),
 257   _region_index_end(region_index_end) {}
 258 
 259 void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) {
 260 
 261   NOT_PRODUCT(TraceTime tm("UpdateDensePrefixTask",
 262     PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
 263 
 264   ParCompactionManager* cm =
 265     ParCompactionManager::gc_thread_compaction_manager(which);
 266 
 267   PSParallelCompact::update_and_deadwood_in_dense_prefix(cm,
 268                                                          _space_id,
 269                                                          _region_index_start,
 270                                                          _region_index_end);
 271 }
 272 
 273 void DrainStacksCompactionTask::do_it(GCTaskManager* manager, uint which) {
 274   assert(Universe::heap()->is_gc_active(), "called outside gc");
 275 
 276   NOT_PRODUCT(TraceTime tm("DrainStacksCompactionTask",
 277     PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
 278 
 279   ParCompactionManager* cm =
 280     ParCompactionManager::gc_thread_compaction_manager(which);
 281 
 282   // Process any regions already in the compaction managers stacks.
 283   cm->drain_region_stacks();
 284 }