src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp

Wed, 03 Mar 2010 14:48:26 -0800

author
jcoomes
date
Wed, 03 Mar 2010 14:48:26 -0800
changeset 1746
2a1472c30599
parent 1383
89e0543e1737
child 1907
c18cbe5936b8
permissions
-rw-r--r--

4396719: Mark Sweep stack overflow on deeply nested Object arrays
Summary: Use an explicit stack for object arrays and process them in chunks.
Reviewed-by: iveresov, apetrusenko

     1 /*
     2  * Copyright 2005-2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 // Move to some global location
    26 #define HAS_BEEN_MOVED 0x1501d01d
    27 // End move to some global location
    30 class MutableSpace;
    31 class PSOldGen;
    32 class ParCompactionManager;
    33 class ObjectStartArray;
    34 class ParallelCompactData;
    35 class ParMarkBitMap;
    37 class ParCompactionManager : public CHeapObj {
    38   friend class ParallelTaskTerminator;
    39   friend class ParMarkBitMap;
    40   friend class PSParallelCompact;
    41   friend class StealRegionCompactionTask;
    42   friend class UpdateAndFillClosure;
    43   friend class RefProcTaskExecutor;
    45  public:
    47 // ------------------------  Don't putback if not needed
    48   // Actions that the compaction manager should take.
    49   enum Action {
    50     Update,
    51     Copy,
    52     UpdateAndCopy,
    53     CopyAndUpdate,
    54     VerifyUpdate,
    55     ResetObjects,
    56     NotValid
    57   };
    58 // ------------------------  End don't putback if not needed
    60  private:
    61   // 32-bit:  4K * 8 = 32KiB; 64-bit:  8K * 16 = 128KiB
    62   #define OBJARRAY_QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
    63   typedef GenericTaskQueue<ObjArrayTask, OBJARRAY_QUEUE_SIZE> ObjArrayTaskQueue;
    64   typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet;
    65   #undef OBJARRAY_QUEUE_SIZE
    67   static ParCompactionManager** _manager_array;
    68   static OopTaskQueueSet*       _stack_array;
    69   static ObjArrayTaskQueueSet*  _objarray_queues;
    70   static ObjectStartArray*      _start_array;
    71   static RegionTaskQueueSet*    _region_array;
    72   static PSOldGen*              _old_gen;
    74 private:
    75   OopTaskQueue                  _marking_stack;
    76   GrowableArray<oop>*           _overflow_stack;
    78   typedef GrowableArray<ObjArrayTask> ObjArrayOverflowStack;
    79   ObjArrayTaskQueue             _objarray_queue;
    80   ObjArrayOverflowStack*        _objarray_overflow_stack;
    82   // Is there a way to reuse the _marking_stack for the
    83   // saving empty regions?  For now just create a different
    84   // type of TaskQueue.
    86 #ifdef USE_RegionTaskQueueWithOverflow
    87   RegionTaskQueueWithOverflow   _region_stack;
    88 #else
    89   RegionTaskQueue               _region_stack;
    90   GrowableArray<size_t>*        _region_overflow_stack;
    91 #endif
    93 #if 1  // does this happen enough to need a per thread stack?
    94   GrowableArray<Klass*>*        _revisit_klass_stack;
    95   GrowableArray<DataLayout*>*   _revisit_mdo_stack;
    96 #endif
    97   static ParMarkBitMap* _mark_bitmap;
    99   Action _action;
   101   static PSOldGen* old_gen()             { return _old_gen; }
   102   static ObjectStartArray* start_array() { return _start_array; }
   103   static OopTaskQueueSet* stack_array()  { return _stack_array; }
   105   static void initialize(ParMarkBitMap* mbm);
   107  protected:
   108   // Array of tasks.  Needed by the ParallelTaskTerminator.
   109   static RegionTaskQueueSet* region_array()      { return _region_array; }
   110   OopTaskQueue*  marking_stack()                 { return &_marking_stack; }
   111   GrowableArray<oop>* overflow_stack()           { return _overflow_stack; }
   112 #ifdef USE_RegionTaskQueueWithOverflow
   113   RegionTaskQueueWithOverflow* region_stack()    { return &_region_stack; }
   114 #else
   115   RegionTaskQueue*  region_stack()               { return &_region_stack; }
   116   GrowableArray<size_t>* region_overflow_stack() {
   117     return _region_overflow_stack;
   118   }
   119 #endif
   121   // Pushes onto the marking stack.  If the marking stack is full,
   122   // pushes onto the overflow stack.
   123   void stack_push(oop obj);
   124   // Do not implement an equivalent stack_pop.  Deal with the
   125   // marking stack and overflow stack directly.
   127   // Pushes onto the region stack.  If the region stack is full,
   128   // pushes onto the region overflow stack.
   129   void region_stack_push(size_t region_index);
   131 public:
   132   Action action() { return _action; }
   133   void set_action(Action v) { _action = v; }
   135   inline static ParCompactionManager* manager_array(int index);
   137   ParCompactionManager();
   138   ~ParCompactionManager();
   140   void allocate_stacks();
   141   void deallocate_stacks();
   142   ParMarkBitMap* mark_bitmap() { return _mark_bitmap; }
   144   // Take actions in preparation for a compaction.
   145   static void reset();
   147   // void drain_stacks();
   149   bool should_update();
   150   bool should_copy();
   151   bool should_verify_only();
   152   bool should_reset_only();
   154 #if 1
   155   // Probably stays as a growable array
   156   GrowableArray<Klass*>* revisit_klass_stack() { return _revisit_klass_stack; }
   157   GrowableArray<DataLayout*>* revisit_mdo_stack() { return _revisit_mdo_stack; }
   158 #endif
   160   // Save oop for later processing.  Must not fail.
   161   void save_for_scanning(oop m);
   162   // Get a oop for scanning.  If returns null, no oop were found.
   163   oop retrieve_for_scanning();
   165   inline void push_objarray(oop obj, size_t index);
   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);
   172   // Access function for compaction managers
   173   static ParCompactionManager* gc_thread_compaction_manager(int index);
   175   static bool steal(int queue_num, int* seed, Task& t) {
   176     return stack_array()->steal(queue_num, seed, t);
   177   }
   179   static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t) {
   180     return _objarray_queues->steal(queue_num, seed, t);
   181   }
   183   static bool steal(int queue_num, int* seed, RegionTask& t) {
   184     return region_array()->steal(queue_num, seed, t);
   185   }
   187   // Process tasks remaining on any marking stack
   188   void follow_marking_stacks();
   189   inline bool marking_stacks_empty() const;
   191   // Process tasks remaining on any stack
   192   void drain_region_stacks();
   194   // Process tasks remaining on any stack
   195   void drain_region_overflow_stack();
   197   // Debugging support
   198 #ifdef ASSERT
   199   bool stacks_have_been_allocated();
   200 #endif
   201 };
   203 inline ParCompactionManager* ParCompactionManager::manager_array(int index) {
   204   assert(_manager_array != NULL, "access of NULL manager_array");
   205   assert(index >= 0 && index <= (int)ParallelGCThreads,
   206     "out of range manager_array access");
   207   return _manager_array[index];
   208 }
   210 bool ParCompactionManager::marking_stacks_empty() const {
   211   return _marking_stack.size() == 0 && _overflow_stack->is_empty() &&
   212     _objarray_queue.size() == 0 && _objarray_overflow_stack->is_empty();
   213 }

mercurial