1 #ifdef USE_PRAGMA_IDENT_HDR
   2 #pragma ident "@(#)psCompactionManager.hpp      1.17 07/05/05 17:05:29 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 //
  29 // psPromotionManager is used by a single thread to manage object survival
  30 // during a scavenge. The promotion manager contains thread local data only.
  31 //
  32 // NOTE! Be carefull when allocating the stacks on cheap. If you are going
  33 // to use a promotion manager in more than one thread, the stacks MUST be
  34 // on cheap. This can lead to memory leaks, though, as they are not auto
  35 // deallocated.
  36 //
  37 // FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate!
  38 //
  39 
  40 // Move to some global location
  41 #define HAS_BEEN_MOVED 0x1501d01d
  42 // End move to some global location
  43 
  44 
  45 class MutableSpace;
  46 class PSOldGen;
  47 class ParCompactionManager;
  48 class ObjectStartArray;
  49 class ParallelCompactData;
  50 class ParMarkBitMap;
  51 
  52 // Move to it's own file if this works out.
  53 
  54 class ParCompactionManager : public CHeapObj {
  55   friend class ParallelTaskTerminator;
  56   friend class ParMarkBitMap;
  57   friend class PSParallelCompact;
  58   friend class StealRegionCompactionTask;
  59   friend class UpdateAndFillClosure;
  60   friend class RefProcTaskExecutor;
  61 
  62  public:
  63 
  64 // ------------------------  Don't putback if not needed
  65   // Actions that the compaction manager should take.
  66   enum Action {
  67     Update,
  68     Copy,
  69     UpdateAndCopy,
  70     CopyAndUpdate,
  71     VerifyUpdate,
  72     ResetObjects,
  73     NotValid
  74   };
  75 // ------------------------  End don't putback if not needed
  76 
  77  private:
  78   static ParCompactionManager** _manager_array;
  79   static OopTaskQueueSet*       _stack_array;
  80   static ObjectStartArray*      _start_array;
  81   static RegionTaskQueueSet*    _region_array;
  82   static PSOldGen*              _old_gen;
  83 
  84   OopTaskQueue                  _marking_stack;
  85   GrowableArray<oop>*           _overflow_stack;
  86   // Is there a way to reuse the _marking_stack for the
  87   // saving empty regions?  For now just create a different
  88   // type of TaskQueue.
  89 
  90 #ifdef USE_RegionTaskQueueWithOverflow
  91   RegionTaskQueueWithOverflow   _region_stack;
  92 #else
  93   RegionTaskQueue               _region_stack;
  94   GrowableArray<size_t>*        _region_overflow_stack;
  95 #endif
  96 
  97 #if 1  // does this happen enough to need a per thread stack?
  98   GrowableArray<Klass*>*        _revisit_klass_stack;
  99 #endif
 100   static ParMarkBitMap* _mark_bitmap;
 101 
 102   Action _action;
 103 
 104   static PSOldGen* old_gen()             { return _old_gen; }
 105   static ObjectStartArray* start_array() { return _start_array; }
 106   static OopTaskQueueSet* stack_array()  { return _stack_array; }
 107 
 108   static void initialize(ParMarkBitMap* mbm);
 109 
 110  protected:
 111   // Array of tasks.  Needed by the ParallelTaskTerminator.
 112   static RegionTaskQueueSet* region_array()      { return _region_array; }
 113   OopTaskQueue*  marking_stack()                 { return &_marking_stack; }
 114   GrowableArray<oop>* overflow_stack()           { return _overflow_stack; }
 115 #ifdef USE_RegionTaskQueueWithOverflow
 116   RegionTaskQueueWithOverflow* region_stack()    { return &_region_stack; }
 117 #else
 118   RegionTaskQueue*  region_stack()               { return &_region_stack; }
 119   GrowableArray<size_t>* region_overflow_stack() {
 120     return _region_overflow_stack;
 121   }
 122 #endif
 123 
 124   // Pushes onto the marking stack.  If the marking stack is full,
 125   // pushes onto the overflow stack.
 126   void stack_push(oop obj);
 127   // Do not implement an equivalent stack_pop.  Deal with the
 128   // marking stack and overflow stack directly.
 129 
 130   // Pushes onto the region stack.  If the region stack is full,
 131   // pushes onto the region overflow stack.
 132   void region_stack_push(size_t region_index);
 133  public:
 134 
 135   Action action() { return _action; }
 136   void set_action(Action v) { _action = v; }
 137 
 138   inline static ParCompactionManager* manager_array(int index);
 139 
 140   ParCompactionManager();
 141   ~ParCompactionManager();
 142 
 143   void allocate_stacks();
 144   void deallocate_stacks();
 145   ParMarkBitMap* mark_bitmap() { return _mark_bitmap; }
 146 
 147   // Take actions in preparation for a compaction.
 148   static void reset();
 149 
 150   // void drain_stacks();
 151 
 152   bool should_update();
 153   bool should_copy();
 154   bool should_verify_only();
 155   bool should_reset_only();
 156 
 157 #if 1
 158   // Probably stays as a growable array
 159   GrowableArray<Klass*>* revisit_klass_stack() { return _revisit_klass_stack; }
 160 #endif
 161 
 162   // Save oop for later processing.  Must not fail.
 163   void save_for_scanning(oop m);
 164   // Get a oop for scanning.  If returns null, no oop were found.
 165   oop retrieve_for_scanning();
 166 
 167   // Save region for later processing.  Must not fail.
 168   void save_for_processing(size_t region_index);
 169   // Get a region for processing.  If returns null, no region were found.
 170   bool retrieve_for_processing(size_t& region_index);
 171 
 172   // Access function for compaction managers
 173   static ParCompactionManager* gc_thread_compaction_manager(int index);
 174 
 175   static bool steal(int queue_num, int* seed, Task& t) {
 176     return stack_array()->steal(queue_num, seed, t);
 177   }
 178 
 179   static bool steal(int queue_num, int* seed, RegionTask& t) {
 180     return region_array()->steal(queue_num, seed, t);
 181   }
 182 
 183   // Process tasks remaining on any stack
 184   void drain_marking_stacks(OopClosure *blk);
 185 
 186   // Process tasks remaining on any stack
 187   void drain_region_stacks();
 188 
 189   // Process tasks remaining on any stack
 190   void drain_region_overflow_stack();
 191 
 192   // Debugging support
 193 #ifdef ASSERT
 194   bool stacks_have_been_allocated();
 195 #endif
 196 };
 197 
 198 inline ParCompactionManager* ParCompactionManager::manager_array(int index) {
 199   assert(_manager_array != NULL, "access of NULL manager_array");
 200   assert(index >= 0 && index <= (int)ParallelGCThreads,
 201     "out of range manager_array access");
 202   return _manager_array[index];
 203 }