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_MAYBE_ENQUEUE, 39 WRITE_BARRIER_ALWAYS_ENQUEUE 40 }; 41 42 static ShenandoahSATBMarkQueueSet _satb_mark_queue_set; 43 44 ShenandoahHeap* _heap; 45 46 public: 47 48 ShenandoahBarrierSet(ShenandoahHeap* heap); 49 50 static SATBMarkQueueSet& satb_mark_queue_set() { 51 return _satb_mark_queue_set; 52 } 53 54 void print_on(outputStream* st) const; 55 56 bool is_a(BarrierSet::Name bsn); 57 58 bool is_aligned(HeapWord* hw); 59 void resize_covered_region(MemRegion mr); 60 61 static void write_ref_array_pre_oop_entry(oop* dst, size_t length); 62 static void write_ref_array_pre_narrow_oop_entry(narrowOop* dst, size_t length); 63 static void write_ref_array_post_entry(HeapWord* dst, size_t length); 64 65 void write_ref_array(HeapWord* start, size_t count); 66 void write_ref_array_work(MemRegion r); 67 68 template <class T> void 69 write_ref_array_pre_work(T* dst, int count); 70 71 void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized); 72 73 void write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized); 74 75 76 // We export this to make it available in cases where the static 77 // type of the barrier set is known. Note that it is non-virtual. 78 template <class T> inline void inline_write_ref_field_pre(T* field, oop new_val); 79 80 // These are the more general virtual versions. 81 void write_ref_field_pre_work(oop* field, oop new_val); 82 void write_ref_field_pre_work(narrowOop* field, oop new_val); 83 void write_ref_field_pre_work(void* field, oop new_val); 84 85 void write_ref_field_work(void* v, oop o, bool release = false); 86 void write_region(MemRegion mr); 87 88 virtual void on_thread_create(Thread* thread); 89 virtual void on_thread_destroy(Thread* thread); 90 virtual void on_thread_attach(JavaThread* thread); 91 virtual void on_thread_detach(JavaThread* thread); 92 93 virtual oop read_barrier(oop src); 94 95 static inline oop resolve_forwarded_not_null(oop p); 96 static inline oop resolve_forwarded(oop p); 97 98 virtual oop write_barrier(oop obj); 99 static oopDesc* write_barrier_IRT(oopDesc* src); 100 static oopDesc* write_barrier_JRT(oopDesc* src); 101 102 virtual oop storeval_barrier(oop obj); 103 104 virtual void keep_alive_barrier(oop obj); 105 106 bool obj_equals(oop obj1, oop obj2); 107 108 #ifdef ASSERT 109 virtual void verify_safe_oop(oop p); 110 #endif 111 112 static void enqueue(oop obj); 113 114 private: 115 bool need_update_refs_barrier(); 116 117 template <class T, bool UPDATE_MATRIX, bool STOREVAL_WRITE_BARRIER, bool ALWAYS_ENQUEUE> 118 void write_ref_array_loop(HeapWord* start, size_t count); 119 120 oop write_barrier_impl(oop obj); 121 122 static void keep_alive_if_weak(DecoratorSet decorators, oop value) { 123 assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); 124 const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0; 125 const bool peek = (decorators & AS_NO_KEEPALIVE) != 0; 126 if (!peek && !on_strong_oop_ref && value != NULL) { 127 ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->keep_alive_barrier(value); 128 } 129 } 130 131 template <typename T> 132 bool arraycopy_loop_1(T* src, T* dst, size_t length, Klass* bound, 133 bool checkcast, bool satb, bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 134 135 template <typename T, bool CHECKCAST> 136 bool arraycopy_loop_2(T* src, T* dst, size_t length, Klass* bound, 137 bool satb, bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 138 139 template <typename T, bool CHECKCAST, bool SATB> 140 bool arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound, 141 bool matrix, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 142 143 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX> 144 bool arraycopy_loop_4(T* src, T* dst, size_t length, Klass* bound, 145 ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode); 146 147 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE> 148 bool arraycopy_loop(T* src, T* dst, size_t length, Klass* bound); 149 150 template <typename T, bool CHECKCAST, bool SATB, bool MATRIX, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE> 151 bool arraycopy_element(T* cur_src, T* cur_dst, Klass* bound, Thread* thread); 152 153 public: 154 // Callbacks for runtime accesses. 155 template <DecoratorSet decorators, typename BarrierSetT = ShenandoahBarrierSet> 156 class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> { 157 typedef BarrierSet::AccessBarrier<decorators, BarrierSetT> Raw; 158 159 public: 160 // Primitive heap accesses. These accessors get resolved when 161 // IN_HEAP is set (e.g. when using the HeapAccess API), it is 162 // not an oop_* overload, and the barrier strength is AS_NORMAL. 163 template <typename T> 164 static T load_in_heap(T* addr) { 165 ShouldNotReachHere(); 166 return Raw::template load<T>(addr); 167 } 168 169 template <typename T> 170 static T load_in_heap_at(oop base, ptrdiff_t offset) { 171 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->read_barrier(base); 172 return Raw::template load_at<T>(base, offset); 173 } 174 175 template <typename T> 176 static void store_in_heap(T* addr, T value) { 177 ShouldNotReachHere(); 178 Raw::store(addr, value); 179 } 180 181 template <typename T> 182 static void store_in_heap_at(oop base, ptrdiff_t offset, T value) { 183 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 184 Raw::store_at(base, offset, value); 185 } 186 187 template <typename T> 188 static T atomic_cmpxchg_in_heap(T new_value, T* addr, T compare_value) { 189 ShouldNotReachHere(); 190 return Raw::atomic_cmpxchg(new_value, addr, compare_value); 191 } 192 193 template <typename T> 194 static T atomic_cmpxchg_in_heap_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { 195 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 196 return Raw::oop_atomic_cmpxchg_at(new_value, base, offset, compare_value); 197 } 198 199 template <typename T> 200 static T atomic_xchg_in_heap(T new_value, T* addr) { 201 ShouldNotReachHere(); 202 return Raw::atomic_xchg(new_value, addr); 203 } 204 205 template <typename T> 206 static T atomic_xchg_in_heap_at(T new_value, oop base, ptrdiff_t offset) { 207 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 208 return Raw::atomic_xchg_at(new_value, base, offset); 209 } 210 211 template <typename T> 212 static bool arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); 213 214 // Heap oop accesses. These accessors get resolved when 215 // IN_HEAP is set (e.g. when using the HeapAccess API), it is 216 // an oop_* overload, and the barrier strength is AS_NORMAL. 217 template <typename T> 218 static oop oop_load_in_heap(T* addr) { 219 ShouldNotReachHere(); 220 oop value = Raw::template oop_load<oop>(addr); 221 keep_alive_if_weak(decorators, value); 222 return value; 223 } 224 225 static oop oop_load_in_heap_at(oop base, ptrdiff_t offset) { 226 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->read_barrier(base); 227 oop value = Raw::template oop_load_at<oop>(base, offset); 228 keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), value); 229 return value; 230 } 231 232 template <typename T> 233 static void oop_store_in_heap(T* addr, oop value) { 234 ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_ref_field_pre_work(addr, value); 235 Raw::oop_store(addr, value); 236 } 237 238 static void oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) { 239 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 240 value = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->storeval_barrier(value); 241 242 oop_store_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), value); 243 } 244 245 template <typename T> 246 static oop oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value); 247 248 static oop oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) { 249 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 250 new_value = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->storeval_barrier(new_value); 251 return oop_atomic_cmpxchg_in_heap(new_value, AccessInternal::oop_field_addr<decorators>(base, offset), compare_value); 252 } 253 254 template <typename T> 255 static oop oop_atomic_xchg_in_heap(oop new_value, T* addr); 256 257 static oop oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) { 258 base = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(base); 259 new_value = ((ShenandoahBarrierSet*) BarrierSet::barrier_set())->storeval_barrier(new_value); 260 return oop_atomic_xchg_in_heap(new_value, AccessInternal::oop_field_addr<decorators>(base, offset)); 261 } 262 263 template <typename T> 264 static bool oop_arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); 265 266 // Clone barrier support 267 static void clone_in_heap(oop src, oop dst, size_t size); 268 269 // Needed for loads on non-heap weak references 270 template <typename T> 271 static oop oop_load_not_in_heap(T* addr) { 272 oop value = Raw::oop_load_not_in_heap(addr); 273 keep_alive_if_weak(decorators, value); 274 return value; 275 } 276 277 static oop resolve(oop obj) { 278 return barrier_set_cast<ShenandoahBarrierSet>(BarrierSet::barrier_set())->write_barrier(obj); 279 } 280 281 static bool equals(oop o1, oop o2) { 282 return barrier_set_cast<ShenandoahBarrierSet>(BarrierSet::barrier_set())->obj_equals(o1, o2); 283 } 284 285 }; 286 287 }; 288 289 template<> 290 struct BarrierSet::GetName<ShenandoahBarrierSet> { 291 static const BarrierSet::Name value = BarrierSet::Shenandoah; 292 }; 293 294 template<> 295 struct BarrierSet::GetType<BarrierSet::Shenandoah> { 296 typedef ShenandoahBarrierSet type; 297 }; 298 299 #endif //SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_HPP