1 /* 2 * Copyright (c) 2013, 2015, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_HPP 25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_HPP 26 27 #include "gc/shared/accessBarrierSupport.hpp" 28 #include "gc/shared/barrierSet.hpp" 29 #include "gc/shenandoah/shenandoahHeap.hpp" 30 #include "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp" 31 32 class ShenandoahBarrierSet: public BarrierSet { 33 private: 34 35 enum ArrayCopyStoreValMode { 36 NONE, 37 READ_BARRIER, 38 WRITE_BARRIER 39 }; 40 41 static ShenandoahSATBMarkQueueSet _satb_mark_queue_set; 42 43 ShenandoahHeap* _heap; 44 45 public: 46 47 ShenandoahBarrierSet(ShenandoahHeap* heap); 48 49 inline static ShenandoahBarrierSet* barrier_set() { 50 return barrier_set_cast<ShenandoahBarrierSet>(BarrierSet::barrier_set()); 51 } 52 53 static SATBMarkQueueSet& satb_mark_queue_set() { 54 return _satb_mark_queue_set; 55 } 56 57 void print_on(outputStream* st) const; 58 59 bool is_a(BarrierSet::Name bsn); 60 61 bool is_aligned(HeapWord* hw); 62 void resize_covered_region(MemRegion mr); 63 64 void write_ref_array(HeapWord* start, size_t count); 65 void write_ref_array_work(MemRegion r); 66 67 template <class T> void 68 write_ref_array_pre_work(T* dst, size_t count); 69 70 void write_ref_array_pre(oop* dst, size_t count, bool dest_uninitialized); 71 72 void write_ref_array_pre(narrowOop* dst, size_t count, bool dest_uninitialized); 73 74 75 // We export this to make it available in cases where the static 76 // type of the barrier set is known. Note that it is non-virtual. 77 template <class T> inline void inline_write_ref_field_pre(T* field, oop new_val); 78 79 // These are the more general virtual versions. 80 void write_ref_field_pre_work(oop* field, oop new_val); 81 void write_ref_field_pre_work(narrowOop* field, oop new_val); 82 void write_ref_field_pre_work(void* field, oop new_val); 83 84 void write_ref_field_work(void* v, oop o, bool release = false); 85 void write_region(MemRegion mr); 86 87 virtual void on_thread_create(Thread* thread); 88 virtual void on_thread_destroy(Thread* thread); 89 virtual void on_thread_attach(JavaThread* thread); 90 virtual void on_thread_detach(JavaThread* thread); 91 92 virtual oop read_barrier(oop src); 93 94 static inline oop resolve_forwarded_not_null(oop p); 95 static inline oop resolve_forwarded(oop p); 96 97 virtual oop write_barrier(oop obj); 98 99 virtual oop storeval_barrier(oop obj); 100 101 virtual void keep_alive_barrier(oop obj); 102 103 bool obj_equals(oop obj1, oop obj2); 104 105 #ifdef ASSERT 106 virtual void verify_safe_oop(oop p); 107 #endif 108 109 void enqueue(oop obj); 110 111 private: 112 inline bool need_update_refs_barrier(); 113 114 template <class T, bool UPDATE_MATRIX, bool STOREVAL_WRITE_BARRIER> 115 void write_ref_array_loop(HeapWord* start, size_t count); 116 117 oop write_barrier_impl(oop obj); 118 119 static void keep_alive_if_weak(DecoratorSet decorators, oop value) { 120 assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); 121 const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0; 122 const bool peek = (decorators & AS_NO_KEEPALIVE) != 0; 123 if (!peek && !on_strong_oop_ref && value != NULL) { 124 ShenandoahBarrierSet::barrier_set()->keep_alive_barrier(value); 125 } 126 } 127 128 template <typename T> 129 bool arraycopy_loop_1(T* src, T* dst, size_t length, Klass* bound, 130 bool checkcast, bool satb, bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 131 132 template <typename T, bool CHECKCAST> 133 bool arraycopy_loop_2(T* src, T* dst, size_t length, Klass* bound, 134 bool satb, bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 135 136 template <typename T, bool CHECKCAST, bool SATB> 137 bool arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound, 138 bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 139 140 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX> 141 bool arraycopy_loop_4(T* src, T* dst, size_t length, Klass* bound, 142 ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 143 144 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE> 145 bool arraycopy_loop(T* src, T* dst, size_t length, Klass* bound); 146 147 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE> 148 bool arraycopy_element(T* cur_src, T* cur_dst, Klass* bound, Thread* thread); 149 150 public: 151 // Callbacks for runtime accesses. 152 template <DecoratorSet decorators, typename BarrierSetT = ShenandoahBarrierSet> 153 class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> { 154 typedef BarrierSet::AccessBarrier<decorators, BarrierSetT> Raw; 155 156 public: 157 // Primitive heap accesses. These accessors get resolved when 158 // IN_HEAP is set (e.g. when using the HeapAccess API), it is 159 // not an oop_* overload, and the barrier strength is AS_NORMAL. 160 template <typename T> 161 static T load_in_heap(T* addr) { 162 ShouldNotReachHere(); 163 return Raw::template load<T>(addr); 164 } 165 166 template <typename T> 167 static T load_in_heap_at(oop base, ptrdiff_t offset) { 168 base = ShenandoahBarrierSet::resolve_forwarded(base); 169 return Raw::template load_at<T>(base, offset); 170 } 171 172 template <typename T> 173 static void store_in_heap(T* addr, T value) { 174 ShouldNotReachHere(); 175 Raw::store(addr, value); 176 } 177 178 template <typename T> 179 static void store_in_heap_at(oop base, ptrdiff_t offset, T value) { 180 base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); 181 Raw::store_at(base, offset, value); 182 } 183 184 template <typename T> 185 static T atomic_cmpxchg_in_heap(T new_value, T* addr, T compare_value) { 186 ShouldNotReachHere(); 187 return Raw::atomic_cmpxchg(new_value, addr, compare_value); 188 } 189 190 template <typename T> 191 static T atomic_cmpxchg_in_heap_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { 192 base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); 193 return Raw::atomic_cmpxchg_at(new_value, base, offset, compare_value); 194 } 195 196 template <typename T> 197 static T atomic_xchg_in_heap(T new_value, T* addr) { 198 ShouldNotReachHere(); 199 return Raw::atomic_xchg(new_value, addr); 200 } 201 202 template <typename T> 203 static T atomic_xchg_in_heap_at(T new_value, oop base, ptrdiff_t offset) { 204 base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); 205 return Raw::atomic_xchg_at(new_value, base, offset); 206 } 207 208 template <typename T> 209 static void arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, 210 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, 211 size_t length); 212 213 // Heap oop accesses. These accessors get resolved when 214 // IN_HEAP is set (e.g. when using the HeapAccess API), it is 215 // an oop_* overload, and the barrier strength is AS_NORMAL. 216 template <typename T> 217 static oop oop_load_in_heap(T* addr) { 218 // ShouldNotReachHere(); 219 oop value = Raw::template oop_load<oop>(addr); 220 keep_alive_if_weak(decorators, value); 221 return value; 222 } 223 224 static oop oop_load_in_heap_at(oop base, ptrdiff_t offset) { 225 base = ShenandoahBarrierSet::resolve_forwarded(base); 226 oop value = Raw::template oop_load_at<oop>(base, offset); 227 keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), value); 228 return value; 229 } 230 231 template <typename T> 232 static void oop_store_in_heap(T* addr, oop value) { 233 ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value); 234 Raw::oop_store(addr, value); 235 } 236 237 static void oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) { 238 base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); 239 value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(value); 240 241 oop_store_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), value); 242 } 243 244 template <typename T> 245 static oop oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value); 246 247 static oop oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) { 248 base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); 249 new_value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value); 250 return oop_atomic_cmpxchg_in_heap(new_value, AccessInternal::oop_field_addr<decorators>(base, offset), compare_value); 251 } 252 253 template <typename T> 254 static oop oop_atomic_xchg_in_heap(oop new_value, T* addr); 255 256 static oop oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) { 257 base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); 258 new_value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value); 259 return oop_atomic_xchg_in_heap(new_value, AccessInternal::oop_field_addr<decorators>(base, offset)); 260 } 261 262 template <typename T> 263 static bool oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, 264 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, 265 size_t length); 266 267 // Clone barrier support 268 static void clone_in_heap(oop src, oop dst, size_t size); 269 270 // Needed for loads on non-heap weak references 271 template <typename T> 272 static oop oop_load_not_in_heap(T* addr) { 273 oop value = Raw::oop_load_not_in_heap(addr); 274 keep_alive_if_weak(decorators, value); 275 return value; 276 } 277 278 static oop resolve(oop obj) { 279 return ShenandoahBarrierSet::barrier_set()->write_barrier(obj); 280 } 281 282 static bool equals(oop o1, oop o2) { 283 return ShenandoahBarrierSet::barrier_set()->obj_equals(o1, o2); 284 } 285 286 }; 287 288 }; 289 290 template<> 291 struct BarrierSet::GetName<ShenandoahBarrierSet> { 292 static const BarrierSet::Name value = BarrierSet::Shenandoah; 293 }; 294 295 template<> 296 struct BarrierSet::GetType<BarrierSet::Shenandoah> { 297 typedef ShenandoahBarrierSet type; 298 }; 299 300 #endif //SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_HPP