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 static SATBMarkQueueSet& satb_mark_queue_set() { 50 return _satb_mark_queue_set; 51 } 52 53 void print_on(outputStream* st) const; 54 55 bool is_a(BarrierSet::Name bsn); 56 57 bool is_aligned(HeapWord* hw); 58 void resize_covered_region(MemRegion mr); 59 60 static void write_ref_array_pre_oop_entry(oop* dst, size_t length); 61 static void write_ref_array_pre_narrow_oop_entry(narrowOop* dst, size_t length); 62 static void write_ref_array_post_entry(HeapWord* dst, size_t length); 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, int count); 69 70 void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized); 71 72 void write_ref_array_pre(narrowOop* dst, int 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 static oopDesc* write_barrier_IRT(oopDesc* src); 99 static oopDesc* write_barrier_JRT(oopDesc* src); 100 101 virtual oop storeval_barrier(oop obj); 102 103 virtual void keep_alive_barrier(oop obj); 104 105 bool obj_equals(oop obj1, oop obj2); 106 107 #ifdef ASSERT 108 virtual void verify_safe_oop(oop p); 109 #endif 110 111 static void enqueue(oop obj); 112 113 private: 114 bool need_update_refs_barrier(); 115 116 template <class T, bool UPDATE_MATRIX, bool STOREVAL_WRITE_BARRIER> 117 void write_ref_array_loop(HeapWord* start, size_t count); 118 119 oop write_barrier_impl(oop obj); 120 121 static void keep_alive_if_weak(DecoratorSet decorators, oop value) { 122 assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); 123 const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0; 124 const bool peek = (decorators & AS_NO_KEEPALIVE) != 0; 125 if (!peek && !on_strong_oop_ref && value != NULL) { 126 ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->keep_alive_barrier(value); 127 } 128 } 129 130 template <typename T> 131 bool arraycopy_loop_1(T* src, T* dst, size_t length, Klass* bound, 132 bool checkcast, bool satb, bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 133 134 template <typename T, bool CHECKCAST> 135 bool arraycopy_loop_2(T* src, T* dst, size_t length, Klass* bound, 136 bool satb, bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 137 138 template <typename T, bool CHECKCAST, bool SATB> 139 bool arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound, 140 bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 141 142 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX> 143 bool arraycopy_loop_4(T* src, T* dst, size_t length, Klass* bound, 144 ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 145 146 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE> 147 bool arraycopy_loop(T* src, T* dst, size_t length, Klass* bound); 148 149 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE> 150 bool arraycopy_element(T* cur_src, T* cur_dst, Klass* bound, Thread* thread); 151 152 public: 153 // Callbacks for runtime accesses. 154 template <DecoratorSet decorators, typename BarrierSetT = ShenandoahBarrierSet> 155 class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> { 156 typedef BarrierSet::AccessBarrier<decorators, BarrierSetT> Raw; 157 158 public: 159 // Primitive heap accesses. These accessors get resolved when 160 // IN_HEAP is set (e.g. when using the HeapAccess API), it is 161 // not an oop_* overload, and the barrier strength is AS_NORMAL. 162 template <typename T> 163 static T load_in_heap(T* addr) { 164 ShouldNotReachHere(); 165 return Raw::template load<T>(addr); 166 } 167 168 template <typename T> 169 static T load_in_heap_at(oop base, ptrdiff_t offset) { 170 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->read_barrier(base); 171 return Raw::template load_at<T>(base, offset); 172 } 173 174 template <typename T> 175 static void store_in_heap(T* addr, T value) { 176 ShouldNotReachHere(); 177 Raw::store(addr, value); 178 } 179 180 template <typename T> 181 static void store_in_heap_at(oop base, ptrdiff_t offset, T value) { 182 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 183 Raw::store_at(base, offset, value); 184 } 185 186 template <typename T> 187 static T atomic_cmpxchg_in_heap(T new_value, T* addr, T compare_value) { 188 ShouldNotReachHere(); 189 return Raw::atomic_cmpxchg(new_value, addr, compare_value); 190 } 191 192 template <typename T> 193 static T atomic_cmpxchg_in_heap_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { 194 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 195 return Raw::oop_atomic_cmpxchg_at(new_value, base, offset, compare_value); 196 } 197 198 template <typename T> 199 static T atomic_xchg_in_heap(T new_value, T* addr) { 200 ShouldNotReachHere(); 201 return Raw::atomic_xchg(new_value, addr); 202 } 203 204 template <typename T> 205 static T atomic_xchg_in_heap_at(T new_value, oop base, ptrdiff_t offset) { 206 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 207 return Raw::atomic_xchg_at(new_value, base, offset); 208 } 209 210 template <typename T> 211 static bool arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, 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*) BarrierSet::barrier_set())->read_barrier(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*) BarrierSet::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*) BarrierSet::barrier_set())->write_barrier(base); 239 value = ((ShenandoahBarrierSet*) BarrierSet::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*) BarrierSet::barrier_set())->write_barrier(base); 249 new_value = ((ShenandoahBarrierSet*) BarrierSet::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*) BarrierSet::barrier_set())->write_barrier(base); 258 new_value = ((ShenandoahBarrierSet*) BarrierSet::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, arrayOop dst_obj, T* src, T* dst, size_t length); 264 265 // Clone barrier support 266 static void clone_in_heap(oop src, oop dst, size_t size); 267 268 // Needed for loads on non-heap weak references 269 template <typename T> 270 static oop oop_load_not_in_heap(T* addr) { 271 oop value = Raw::oop_load_not_in_heap(addr); 272 keep_alive_if_weak(decorators, value); 273 return value; 274 } 275 276 static oop resolve(oop obj) { 277 return barrier_set_cast<ShenandoahBarrierSet>(BarrierSet::barrier_set())->write_barrier(obj); 278 } 279 280 static bool equals(oop o1, oop o2) { 281 return barrier_set_cast<ShenandoahBarrierSet>(BarrierSet::barrier_set())->obj_equals(o1, o2); 282 } 283 284 }; 285 286 }; 287 288 template<> 289 struct BarrierSet::GetName<ShenandoahBarrierSet> { 290 static const BarrierSet::Name value = BarrierSet::Shenandoah; 291 }; 292 293 template<> 294 struct BarrierSet::GetType<BarrierSet::Shenandoah> { 295 typedef ShenandoahBarrierSet type; 296 }; 297 298 #endif //SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_HPP