< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp

Print this page
rev 59333 : 8245240: Shenandoah: support nesting evacuation OOM scope


  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 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHTHREADLOCALDATA_HPP
  26 #define SHARE_GC_SHENANDOAH_SHENANDOAHTHREADLOCALDATA_HPP
  27 
  28 #include "gc/shared/plab.hpp"
  29 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  30 #include "gc/shenandoah/shenandoahCodeRoots.hpp"
  31 #include "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp"
  32 #include "runtime/thread.hpp"
  33 #include "utilities/debug.hpp"
  34 #include "utilities/sizes.hpp"
  35 










  36 class ShenandoahThreadLocalData {
  37 public:
  38   static const uint INVALID_WORKER_ID = uint(-1);
  39 
  40 private:
  41   char _gc_state;
  42   char _oom_during_evac;
  43   ShenandoahSATBMarkQueue _satb_mark_queue;
  44   PLAB* _gclab;
  45   size_t _gclab_size;
  46   uint  _worker_id;
  47   bool _force_satb_flush;
  48   int  _disarmed_value;
  49 
  50   ShenandoahThreadLocalData() :
  51     _gc_state(0),
  52     _oom_during_evac(0),
  53     _satb_mark_queue(&ShenandoahBarrierSet::satb_mark_queue_set()),
  54     _gclab(NULL),
  55     _gclab_size(0),
  56     _worker_id(INVALID_WORKER_ID),
  57     _force_satb_flush(false),
  58     _disarmed_value(0) {


  59 
  60     // At least on x86_64, nmethod entry barrier encodes _disarmed_value offset
  61     // in instruction as disp8 immed
  62     assert(in_bytes(disarmed_value_offset()) < 128, "Offset range check");
  63   }
  64 
  65   ~ShenandoahThreadLocalData() {
  66     if (_gclab != NULL) {
  67       delete _gclab;
  68     }
  69   }
  70 
  71   static ShenandoahThreadLocalData* data(Thread* thread) {
  72     assert(UseShenandoahGC, "Sanity");
  73     return thread->gc_data<ShenandoahThreadLocalData>();
  74   }
  75 
  76   static ByteSize satb_mark_queue_offset() {
  77     return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _satb_mark_queue);
  78   }
  79 
  80 public:
  81   static void create(Thread* thread) {
  82     new (data(thread)) ShenandoahThreadLocalData();
  83   }
  84 
  85   static void destroy(Thread* thread) {
  86     data(thread)->~ShenandoahThreadLocalData();
  87   }
  88 
  89   static SATBMarkQueue& satb_mark_queue(Thread* thread) {
  90     return data(thread)->_satb_mark_queue;
  91   }
  92 
  93   static bool is_oom_during_evac(Thread* thread) {
  94     return (data(thread)->_oom_during_evac & 1) == 1;
  95   }
  96 
  97   static void set_oom_during_evac(Thread* thread, bool oom) {
  98     if (oom) {
  99       data(thread)->_oom_during_evac |= 1;
 100     } else {
 101       data(thread)->_oom_during_evac &= ~1;
 102     }
 103   }
 104 
 105   static void set_gc_state(Thread* thread, char gc_state) {
 106     data(thread)->_gc_state = gc_state;
 107   }
 108 
 109   static char gc_state(Thread* thread) {
 110     return data(thread)->_gc_state;
 111   }
 112 
 113   static void set_worker_id(Thread* thread, uint id) {
 114     assert(thread->is_Worker_thread(), "Must be a worker thread");
 115     data(thread)->_worker_id = id;
 116   }
 117 
 118   static uint worker_id(Thread* thread) {
 119     assert(thread->is_Worker_thread(), "Must be a worker thread");
 120     return data(thread)->_worker_id;
 121   }
 122 
 123   static void set_force_satb_flush(Thread* thread, bool v) {
 124     data(thread)->_force_satb_flush = v;


 134     data(thread)->_gclab = new PLAB(PLAB::min_size());
 135     data(thread)->_gclab_size = 0;
 136   }
 137 
 138   static PLAB* gclab(Thread* thread) {
 139     return data(thread)->_gclab;
 140   }
 141 
 142   static size_t gclab_size(Thread* thread) {
 143     return data(thread)->_gclab_size;
 144   }
 145 
 146   static void set_gclab_size(Thread* thread, size_t v) {
 147     data(thread)->_gclab_size = v;
 148   }
 149 
 150   static void set_disarmed_value(Thread* thread, int value) {
 151     data(thread)->_disarmed_value = value;
 152   }
 153 
 154 #ifdef ASSERT
 155   static void set_evac_allowed(Thread* thread, bool evac_allowed) {
 156     if (evac_allowed) {
 157       data(thread)->_oom_during_evac |= 2;




 158     } else {
 159       data(thread)->_oom_during_evac &= ~2;

 160     }



















 161   }
 162 
 163   static bool is_evac_allowed(Thread* thread) {
 164     return (data(thread)->_oom_during_evac & 2) == 2;
 165   }
 166 #endif
 167 
 168   // Offsets
 169   static ByteSize satb_mark_queue_active_offset() {
 170     return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active();
 171   }
 172 
 173   static ByteSize satb_mark_queue_index_offset() {
 174     return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index();
 175   }
 176 
 177   static ByteSize satb_mark_queue_buffer_offset() {
 178     return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf();
 179   }
 180 
 181   static ByteSize gc_state_offset() {
 182     return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _gc_state);
 183   }
 184 
 185   static ByteSize disarmed_value_offset() {
 186     return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _disarmed_value);


  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 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHTHREADLOCALDATA_HPP
  26 #define SHARE_GC_SHENANDOAH_SHENANDOAHTHREADLOCALDATA_HPP
  27 
  28 #include "gc/shared/plab.hpp"
  29 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  30 #include "gc/shenandoah/shenandoahCodeRoots.hpp"
  31 #include "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp"
  32 #include "runtime/thread.hpp"
  33 #include "utilities/debug.hpp"
  34 #include "utilities/sizes.hpp"
  35 
  36 /* Highest bit indicates if current thread encountered OOM
  37  * Remaining bits represent evacuation scope nesting level
  38  */
  39 typedef struct {
  40   uint8_t _nesting_level : 7;
  41   uint8_t _is_evac_oom   : 1;
  42 } ShenandoahEvacOOMState;
  43 
  44 STATIC_ASSERT(sizeof(ShenandoahEvacOOMState) == sizeof(char));
  45 
  46 class ShenandoahThreadLocalData {
  47 public:
  48   static const uint INVALID_WORKER_ID = uint(-1);
  49 
  50 private:
  51   char _gc_state;
  52   ShenandoahEvacOOMState  _oom_during_evac;
  53   ShenandoahSATBMarkQueue _satb_mark_queue;
  54   PLAB* _gclab;
  55   size_t _gclab_size;
  56   uint  _worker_id;
  57   bool _force_satb_flush;
  58   int  _disarmed_value;
  59 
  60   ShenandoahThreadLocalData() :
  61     _gc_state(0),

  62     _satb_mark_queue(&ShenandoahBarrierSet::satb_mark_queue_set()),
  63     _gclab(NULL),
  64     _gclab_size(0),
  65     _worker_id(INVALID_WORKER_ID),
  66     _force_satb_flush(false),
  67     _disarmed_value(0) {
  68     _oom_during_evac._nesting_level = 0;
  69     _oom_during_evac._is_evac_oom = 0;
  70 
  71     // At least on x86_64, nmethod entry barrier encodes _disarmed_value offset
  72     // in instruction as disp8 immed
  73     assert(in_bytes(disarmed_value_offset()) < 128, "Offset range check");
  74   }
  75 
  76   ~ShenandoahThreadLocalData() {
  77     if (_gclab != NULL) {
  78       delete _gclab;
  79     }
  80   }
  81 
  82   static ShenandoahThreadLocalData* data(Thread* thread) {
  83     assert(UseShenandoahGC, "Sanity");
  84     return thread->gc_data<ShenandoahThreadLocalData>();
  85   }
  86 
  87   static ByteSize satb_mark_queue_offset() {
  88     return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _satb_mark_queue);
  89   }
  90 
  91 public:
  92   static void create(Thread* thread) {
  93     new (data(thread)) ShenandoahThreadLocalData();
  94   }
  95 
  96   static void destroy(Thread* thread) {
  97     data(thread)->~ShenandoahThreadLocalData();
  98   }
  99 
 100   static SATBMarkQueue& satb_mark_queue(Thread* thread) {
 101     return data(thread)->_satb_mark_queue;
 102   }
 103 












 104   static void set_gc_state(Thread* thread, char gc_state) {
 105     data(thread)->_gc_state = gc_state;
 106   }
 107 
 108   static char gc_state(Thread* thread) {
 109     return data(thread)->_gc_state;
 110   }
 111 
 112   static void set_worker_id(Thread* thread, uint id) {
 113     assert(thread->is_Worker_thread(), "Must be a worker thread");
 114     data(thread)->_worker_id = id;
 115   }
 116 
 117   static uint worker_id(Thread* thread) {
 118     assert(thread->is_Worker_thread(), "Must be a worker thread");
 119     return data(thread)->_worker_id;
 120   }
 121 
 122   static void set_force_satb_flush(Thread* thread, bool v) {
 123     data(thread)->_force_satb_flush = v;


 133     data(thread)->_gclab = new PLAB(PLAB::min_size());
 134     data(thread)->_gclab_size = 0;
 135   }
 136 
 137   static PLAB* gclab(Thread* thread) {
 138     return data(thread)->_gclab;
 139   }
 140 
 141   static size_t gclab_size(Thread* thread) {
 142     return data(thread)->_gclab_size;
 143   }
 144 
 145   static void set_gclab_size(Thread* thread, size_t v) {
 146     data(thread)->_gclab_size = v;
 147   }
 148 
 149   static void set_disarmed_value(Thread* thread, int value) {
 150     data(thread)->_disarmed_value = value;
 151   }
 152 
 153   // Evacuation OOM handling
 154   static bool is_oom_during_evac(Thread* thread) {
 155     return data(thread)->_oom_during_evac._is_evac_oom == 1;
 156   }
 157 
 158   static void set_oom_during_evac(Thread* thread, bool oom) {
 159     if (oom) {
 160       data(thread)->_oom_during_evac._is_evac_oom = 1;
 161     } else {
 162       data(thread)->_oom_during_evac._is_evac_oom = 0;
 163     }
 164   }
 165 
 166   static uint8_t evac_oom_scope_level(Thread* thread) {
 167     return data(thread)->_oom_during_evac._nesting_level;
 168   }
 169 
 170   // Push the scope one level deeper, return previous level
 171   static uint8_t push_evac_oom_scope(Thread* thread) {
 172     uint8_t level = evac_oom_scope_level(thread);
 173     assert(level < 127, "Overflow nesting level");
 174     data(thread)->_oom_during_evac._nesting_level = level + 1;
 175     return level;
 176   }
 177 
 178   // Pop the scope by one level, return previous level
 179   static uint8_t pop_evac_oom_scope(Thread* thread) {
 180     uint8_t level = evac_oom_scope_level(thread);
 181     assert(level > 0, "Underflow nesting level");
 182     data(thread)->_oom_during_evac._nesting_level = level - 1;
 183     return level;
 184   }
 185 
 186   static bool is_evac_allowed(Thread* thread) {
 187     return evac_oom_scope_level(thread) > 0;
 188   }

 189 
 190   // Offsets
 191   static ByteSize satb_mark_queue_active_offset() {
 192     return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active();
 193   }
 194 
 195   static ByteSize satb_mark_queue_index_offset() {
 196     return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index();
 197   }
 198 
 199   static ByteSize satb_mark_queue_buffer_offset() {
 200     return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf();
 201   }
 202 
 203   static ByteSize gc_state_offset() {
 204     return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _gc_state);
 205   }
 206 
 207   static ByteSize disarmed_value_offset() {
 208     return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _disarmed_value);
< prev index next >