< prev index next >

src/hotspot/share/memory/vtBuffer.hpp

Print this page




 101 
 102   static size_t max_alloc_size() {
 103     return chunk_size() - align_object_size(sizeof (VTBufferChunk));
 104   }
 105 
 106   static VTBufferChunk* chunk(void* address) {
 107     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)address & chunk_mask());
 108     assert(c->is_valid(), "Sanity check");
 109     return c;
 110   }
 111 
 112   static bool check_buffered(void* address) {
 113     assert(address != NULL, "Sanity check");
 114     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)address & chunk_mask());
 115     return c->is_valid();
 116   }
 117 
 118   bool contains(void* address) {
 119     return address > (char*)chunk(address) && address < ((char*)chunk(address) + chunk_size());
 120   }


 121 };
 122 













 123 class VTBuffer : AllStatic {
 124   friend class VMStructs;
 125 private:
 126   static VTBufferChunk* _free_list;
 127   static Mutex* _pool_lock;
 128   static int _pool_counter;
 129   static int _max_pool_counter;
 130   static int _total_allocated;
 131   static int _total_deallocated;
 132   static int _total_failed;
 133   static const int _max_free_list = 64;  // Should be tunable
 134 
 135 public:
 136   static Mutex* lock() { return _pool_lock; }
 137   static oop allocate_value(ValueKlass* k, TRAPS);
 138   static bool allocate_vt_chunk(JavaThread* thread);
 139   static void recycle_chunk(JavaThread* thread, VTBufferChunk* chunk);
 140   static void return_vt_chunk(JavaThread* thread, VTBufferChunk* chunk);
 141 
 142   static int in_pool() { return _pool_counter; }
 143   static int max_in_pool() { return _max_pool_counter; }
 144   static int total_allocated() { return _total_allocated; }
 145   static int total_deallocated() { return _total_deallocated; }
 146   static int total_failed() { return _total_failed; }
 147 
 148   static bool is_in_vt_buffer(const void* p) {

 149     intptr_t chunk_mask = (~(VTBufferChunk::chunk_size() - 1));
 150     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)p & chunk_mask);
 151     return c->is_valid();
 152   }
 153 
 154   static bool value_belongs_to_frame(oop p, frame *f);

 155   static void recycle_vt_in_frame(JavaThread* thread, frame* f);
 156   static void recycle_vtbuffer(JavaThread *thread, frame f);
 157   static address relocate_value(address old, address previous, int previous_size_in_words);
 158   static oop relocate_return_value(JavaThread* thread, frame fr, oop old);
 159 
 160   static void fix_frame_vt_alloc_ptr(frame fr, VTBufferChunk* chunk);
 161 











 162 };
 163 
 164 struct VT_relocation_entry {
 165   int chunk_index;
 166   address old_ptr;
 167   address new_ptr;

 168 };
 169 
 170 
 171 class BufferedValuesMarking : public BufferedValueClosure {
 172   frame* _frame;
 173   struct VT_relocation_entry* _reloc_table;
 174   int _size;
 175   int* _index;
 176 public:
 177   BufferedValuesMarking(frame* frame, struct VT_relocation_entry* reloc_table, int size, int* index) {
 178     _frame = frame;
 179     _reloc_table = reloc_table;
 180     _size = size;
 181     _index = index;
 182   }
 183   virtual void do_buffered_value(oop* p);
 184 };
 185 
 186 class BufferedValuesPointersUpdate : public BufferedValueClosure {
 187   frame* _frame;
 188 public:
 189   BufferedValuesPointersUpdate(frame* frame) {
 190     _frame = frame;
 191   }
 192   virtual void do_buffered_value(oop* p);






















 193 };
 194 
 195 #endif /* SHARE_VM_MEMORY_VTBUFFER_HPP */


 101 
 102   static size_t max_alloc_size() {
 103     return chunk_size() - align_object_size(sizeof (VTBufferChunk));
 104   }
 105 
 106   static VTBufferChunk* chunk(void* address) {
 107     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)address & chunk_mask());
 108     assert(c->is_valid(), "Sanity check");
 109     return c;
 110   }
 111 
 112   static bool check_buffered(void* address) {
 113     assert(address != NULL, "Sanity check");
 114     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)address & chunk_mask());
 115     return c->is_valid();
 116   }
 117 
 118   bool contains(void* address) {
 119     return address > (char*)chunk(address) && address < ((char*)chunk(address) + chunk_size());
 120   }
 121 
 122   void zap(void *start);
 123 };
 124 
 125 /* VTBuffer is a thread-local buffer used to store values, or TLVB (Thread-Local Value Buffer).
 126  * Values allocated in the TLVB have the same layout as value allocated in the Java heap:
 127  * same header size, same offsets for fields. The only difference is on the meaning of the
 128  * mark word: in a buffered value, the mark word contains an oop pointing to the Java mirror
 129  * of the value's class, with the two least significant bits used for internal marking.
 130  * Values allocated in the TLVB are references through oops, however, because TLVBs are not
 131  * part of the Java heap, those oops *must never be exposed to GCs*. But buffered values
 132  * can contain references to Java heap allocated objects or values, in addition to the
 133  * reference to the Java mirror, and these oops have to be processed by GC. The solution is
 134  * to let GC closures iterate over the internal oops, but not directly on the buffered value
 135  * itself (see ValueKlass::iterate_over_inside_oops() method).
 136  */
 137 
 138 class VTBuffer : AllStatic {
 139   friend class VMStructs;
 140 private:
 141   static VTBufferChunk* _free_list;
 142   static Mutex* _pool_lock;
 143   static int _pool_counter;
 144   static int _max_pool_counter;
 145   static int _total_allocated;
 146   static int _total_deallocated;
 147   static int _total_failed;
 148   static const int _max_free_list = 64;  // Should be tunable
 149 
 150 public:
 151   static Mutex* lock() { return _pool_lock; }
 152   static oop allocate_value(ValueKlass* k, TRAPS);
 153   static bool allocate_vt_chunk(JavaThread* thread);
 154   static void recycle_chunk(JavaThread* thread, VTBufferChunk* chunk);
 155   static void return_vt_chunk(JavaThread* thread, VTBufferChunk* chunk);
 156 
 157   static int in_pool() { return _pool_counter; }
 158   static int max_in_pool() { return _max_pool_counter; }
 159   static int total_allocated() { return _total_allocated; }
 160   static int total_deallocated() { return _total_deallocated; }
 161   static int total_failed() { return _total_failed; }
 162 
 163   static bool is_in_vt_buffer(const void* p) {
 164     if (p == NULL) return false;
 165     intptr_t chunk_mask = (~(VTBufferChunk::chunk_size() - 1));
 166     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)p & chunk_mask);
 167     return c->is_valid();
 168   }
 169 
 170   static bool value_belongs_to_frame(oop p, frame *f);
 171   static bool is_value_allocated_after(oop p, void* a);
 172   static void recycle_vt_in_frame(JavaThread* thread, frame* f);
 173   static void recycle_vtbuffer(JavaThread *thread, void* alloc_ptr);
 174   static address relocate_value(address old, address previous, int previous_size_in_words);
 175   static oop relocate_return_value(JavaThread* thread, void* alloc_ptr, oop old);
 176 
 177   static void fix_frame_vt_alloc_ptr(frame fr, VTBufferChunk* chunk);
 178 
 179   enum Mark {
 180     mark_A = 1,
 181     mark_B = 2,
 182     mark_mask = 3
 183   };
 184 
 185   static Mark switch_mark(Mark m) {
 186     assert(m == mark_A || m == mark_B, "Sanity check");
 187     return m == mark_A ? mark_B : mark_A;
 188   }
 189 
 190 };
 191 
 192 struct VT_relocation_entry {
 193   int chunk_index;
 194   address old_ptr;
 195   address new_ptr;
 196   markOop mark_word;
 197 };
 198 
 199 
 200 class BufferedValuesMarking : public BufferedValueClosure {
 201   frame* _frame;
 202   struct VT_relocation_entry* _reloc_table;
 203   int _size;
 204   int* _index;
 205 public:
 206   BufferedValuesMarking(frame* frame, struct VT_relocation_entry* reloc_table, int size, int* index) {
 207     _frame = frame;
 208     _reloc_table = reloc_table;
 209     _size = size;
 210     _index = index;
 211   }
 212   virtual void do_buffered_value(oop* p);
 213 };
 214 
 215 class BufferedValuesPointersUpdate : public BufferedValueClosure {
 216   frame* _frame;
 217 public:
 218   BufferedValuesPointersUpdate(frame* frame) {
 219     _frame = frame;
 220   }
 221   virtual void do_buffered_value(oop* p);
 222 };
 223 
 224 /* Value buffered in a TLVB expose their internal oops as roots for GCs.
 225  * A GC root must only be processed once by each GC closure. However,
 226  * a Java Thread can have multiple oops (aliases) pointing to the same
 227  * buffered value (from local variable entries, operand stack slots,
 228  * Handles or runtime data structures). To prevent duplicated processing
 229  * of a buffered value, each function processing a Java Thread's GC roots
 230  * must allocates a BufferedValuesDealiaser which uses a marking mechanism
 231  * to avoid processing a buffered value twice.
 232  */
 233 class BufferedValuesDealiaser : public StackObj {
 234 private:
 235   const JavaThread* _target;
 236   VTBuffer::Mark _current_mark;
 237 
 238 public:
 239   BufferedValuesDealiaser(JavaThread* thread);
 240   VTBuffer::Mark current_mark() const { return _current_mark; }
 241   void oops_do(OopClosure* f, oop value);
 242 
 243   ~BufferedValuesDealiaser();
 244 };
 245 
 246 #endif /* SHARE_VM_MEMORY_VTBUFFER_HPP */
< prev index next >