1 /*
   2  * Copyright (c) 2002, 2010, 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 "precompiled.hpp"
  26 #include "classfile/systemDictionary.hpp"
  27 #include "code/codeCache.hpp"
  28 #include "gc_implementation/parallelScavenge/cardTableExtension.hpp"
  29 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
  30 #include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
  31 #include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
  32 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
  33 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
  34 #include "gc_implementation/parallelScavenge/psTasks.hpp"
  35 #include "memory/iterator.hpp"
  36 #include "memory/universe.hpp"
  37 #include "oops/oop.inline.hpp"
  38 #include "oops/oop.psgc.inline.hpp"
  39 #include "runtime/fprofiler.hpp"
  40 #include "runtime/thread.hpp"
  41 #include "runtime/vmThread.hpp"
  42 #include "services/management.hpp"
  43 #include "utilities/taskqueue.hpp"
  44 
  45 //
  46 // ScavengeRootsTask
  47 //
  48 
  49 // Define before use
  50 class PSScavengeRootsClosure: public OopClosure {
  51  private:
  52   PSPromotionManager* _promotion_manager;
  53 
  54  protected:
  55   template <class T> void do_oop_work(T *p) {
  56     if (PSScavenge::should_scavenge(p)) {
  57       // We never card mark roots, maybe call a func without test?
  58       PSScavenge::copy_and_push_safe_barrier(_promotion_manager, p);
  59     }
  60   }
  61  public:
  62   PSScavengeRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { }
  63   void do_oop(oop* p)       { PSScavengeRootsClosure::do_oop_work(p); }
  64   void do_oop(narrowOop* p) { PSScavengeRootsClosure::do_oop_work(p); }
  65 };
  66 
  67 void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
  68   assert(Universe::heap()->is_gc_active(), "called outside gc");
  69 
  70   PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
  71   PSScavengeRootsClosure roots_closure(pm);
  72 
  73   switch (_root_type) {
  74     case universe:
  75       Universe::oops_do(&roots_closure);
  76       ReferenceProcessor::oops_do(&roots_closure);
  77       break;
  78 
  79     case jni_handles:
  80       JNIHandles::oops_do(&roots_closure);
  81       break;
  82 
  83     case threads:
  84     {
  85       ResourceMark rm;
  86       Threads::oops_do(&roots_closure, NULL);
  87     }
  88     break;
  89 
  90     case object_synchronizer:
  91       ObjectSynchronizer::oops_do(&roots_closure);
  92       break;
  93 
  94     case flat_profiler:
  95       FlatProfiler::oops_do(&roots_closure);
  96       break;
  97 
  98     case system_dictionary:
  99       SystemDictionary::oops_do(&roots_closure);
 100       break;
 101 
 102     case management:
 103       Management::oops_do(&roots_closure);
 104       break;
 105 
 106     case jvmti:
 107       JvmtiExport::oops_do(&roots_closure);
 108       break;
 109 
 110 
 111     case code_cache:
 112       {
 113         CodeBlobToOopClosure each_scavengable_code_blob(&roots_closure, /*do_marking=*/ true);
 114         CodeCache::scavenge_root_nmethods_do(&each_scavengable_code_blob);
 115       }
 116       break;
 117 
 118     default:
 119       fatal("Unknown root type");
 120   }
 121 
 122   // Do the real work
 123   pm->drain_stacks(false);
 124 }
 125 
 126 //
 127 // ThreadRootsTask
 128 //
 129 
 130 void ThreadRootsTask::do_it(GCTaskManager* manager, uint which) {
 131   assert(Universe::heap()->is_gc_active(), "called outside gc");
 132 
 133   PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
 134   PSScavengeRootsClosure roots_closure(pm);
 135   CodeBlobToOopClosure roots_in_blobs(&roots_closure, /*do_marking=*/ true);
 136 
 137   if (_java_thread != NULL)
 138     _java_thread->oops_do(&roots_closure, &roots_in_blobs);
 139 
 140   if (_vm_thread != NULL)
 141     _vm_thread->oops_do(&roots_closure, &roots_in_blobs);
 142 
 143   // Do the real work
 144   pm->drain_stacks(false);
 145 }
 146 
 147 //
 148 // StealTask
 149 //
 150 
 151 StealTask::StealTask(ParallelTaskTerminator* t) :
 152   _terminator(t) {}
 153 
 154 void StealTask::do_it(GCTaskManager* manager, uint which) {
 155   assert(Universe::heap()->is_gc_active(), "called outside gc");
 156 
 157   PSPromotionManager* pm =
 158     PSPromotionManager::gc_thread_promotion_manager(which);
 159   pm->drain_stacks(true);
 160   guarantee(pm->stacks_empty(),
 161             "stacks should be empty at this point");
 162 
 163   int random_seed = 17;
 164   while(true) {
 165     StarTask p;
 166     if (PSPromotionManager::steal_depth(which, &random_seed, p)) {
 167       TASKQUEUE_STATS_ONLY(pm->record_steal(p));
 168       pm->process_popped_location_depth(p);
 169       pm->drain_stacks_depth(true);
 170     } else {
 171       if (terminator()->offer_termination()) {
 172         break;
 173       }
 174     }
 175   }
 176   guarantee(pm->stacks_empty(), "stacks should be empty at this point");
 177 }
 178 
 179 //
 180 // SerialOldToYoungRootsTask
 181 //
 182 
 183 void SerialOldToYoungRootsTask::do_it(GCTaskManager* manager, uint which) {
 184   assert(_gen != NULL, "Sanity");
 185   assert(_gen->object_space()->contains(_gen_top) || _gen_top == _gen->object_space()->top(), "Sanity");
 186 
 187   {
 188     PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
 189 
 190     assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
 191     CardTableExtension* card_table = (CardTableExtension *)Universe::heap()->barrier_set();
 192     // FIX ME! Assert that card_table is the type we believe it to be.
 193 
 194     card_table->scavenge_contents(_gen->start_array(),
 195                                   _gen->object_space(),
 196                                   _gen_top,
 197                                   pm);
 198 
 199     // Do the real work
 200     pm->drain_stacks(false);
 201   }
 202 }
 203 
 204 //
 205 // OldToYoungRootsTask
 206 //
 207 
 208 void OldToYoungRootsTask::do_it(GCTaskManager* manager, uint which) {
 209   assert(_gen != NULL, "Sanity");
 210   assert(_gen->object_space()->contains(_gen_top) || _gen_top == _gen->object_space()->top(), "Sanity");
 211   assert(_stripe_number < ParallelGCThreads, "Sanity");
 212 
 213   {
 214     PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
 215 
 216     assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
 217     CardTableExtension* card_table = (CardTableExtension *)Universe::heap()->barrier_set();
 218     // FIX ME! Assert that card_table is the type we believe it to be.
 219 
 220     card_table->scavenge_contents_parallel(_gen->start_array(),
 221                                            _gen->object_space(),
 222                                            _gen_top,
 223                                            pm,
 224                                            _stripe_number);
 225 
 226     // Do the real work
 227     pm->drain_stacks(false);
 228   }
 229 }