1 /* 2 * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 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 #ifndef SHARE_GC_X_XBARRIERSET_INLINE_HPP 25 #define SHARE_GC_X_XBARRIERSET_INLINE_HPP 26 27 #include "gc/x/xBarrierSet.hpp" 28 29 #include "gc/shared/accessBarrierSupport.inline.hpp" 30 #include "gc/x/xBarrier.inline.hpp" 31 #include "oops/inlineKlass.inline.hpp" 32 #include "utilities/debug.hpp" 33 34 template <DecoratorSet decorators, typename BarrierSetT> 35 template <DecoratorSet expected> 36 inline void XBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_present() { 37 if ((decorators & expected) == 0) { 38 fatal("Using unsupported access decorators"); 39 } 40 } 41 42 template <DecoratorSet decorators, typename BarrierSetT> 43 template <DecoratorSet expected> 44 inline void XBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_absent() { 45 if ((decorators & expected) != 0) { 46 fatal("Using unsupported access decorators"); 47 } 48 } 49 50 template <DecoratorSet decorators, typename BarrierSetT> 51 inline oop* XBarrierSet::AccessBarrier<decorators, BarrierSetT>::field_addr(oop base, ptrdiff_t offset) { 52 assert(base != nullptr, "Invalid base"); 53 return reinterpret_cast<oop*>(reinterpret_cast<intptr_t>((void*)base) + offset); 54 } 55 56 template <DecoratorSet decorators, typename BarrierSetT> 57 template <typename T> 58 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::load_barrier_on_oop_field_preloaded(T* addr, oop o) { 59 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 60 61 if (HasDecorator<decorators, AS_NO_KEEPALIVE>::value) { 62 if (HasDecorator<decorators, ON_STRONG_OOP_REF>::value) { 63 return XBarrier::weak_load_barrier_on_oop_field_preloaded(addr, o); 64 } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) { 65 return XBarrier::weak_load_barrier_on_weak_oop_field_preloaded(addr, o); 66 } else { 67 assert((HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value), "Must be"); 68 return XBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(addr, o); 69 } 70 } else { 71 if (HasDecorator<decorators, ON_STRONG_OOP_REF>::value) { 72 return XBarrier::load_barrier_on_oop_field_preloaded(addr, o); 73 } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) { 74 return XBarrier::load_barrier_on_weak_oop_field_preloaded(addr, o); 75 } else { 76 assert((HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value), "Must be"); 77 return XBarrier::load_barrier_on_phantom_oop_field_preloaded(addr, o); 78 } 79 } 80 } 81 82 template <DecoratorSet decorators, typename BarrierSetT> 83 template <typename T> 84 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::load_barrier_on_unknown_oop_field_preloaded(oop base, ptrdiff_t offset, T* addr, oop o) { 85 verify_decorators_present<ON_UNKNOWN_OOP_REF>(); 86 87 const DecoratorSet decorators_known_strength = 88 AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset); 89 90 if (HasDecorator<decorators, AS_NO_KEEPALIVE>::value) { 91 if (decorators_known_strength & ON_STRONG_OOP_REF) { 92 return XBarrier::weak_load_barrier_on_oop_field_preloaded(addr, o); 93 } else if (decorators_known_strength & ON_WEAK_OOP_REF) { 94 return XBarrier::weak_load_barrier_on_weak_oop_field_preloaded(addr, o); 95 } else { 96 assert(decorators_known_strength & ON_PHANTOM_OOP_REF, "Must be"); 97 return XBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(addr, o); 98 } 99 } else { 100 if (decorators_known_strength & ON_STRONG_OOP_REF) { 101 return XBarrier::load_barrier_on_oop_field_preloaded(addr, o); 102 } else if (decorators_known_strength & ON_WEAK_OOP_REF) { 103 return XBarrier::load_barrier_on_weak_oop_field_preloaded(addr, o); 104 } else { 105 assert(decorators_known_strength & ON_PHANTOM_OOP_REF, "Must be"); 106 return XBarrier::load_barrier_on_phantom_oop_field_preloaded(addr, o); 107 } 108 } 109 } 110 111 // 112 // In heap 113 // 114 template <DecoratorSet decorators, typename BarrierSetT> 115 template <typename T> 116 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap(T* addr) { 117 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 118 119 const oop o = Raw::oop_load_in_heap(addr); 120 return load_barrier_on_oop_field_preloaded(addr, o); 121 } 122 123 template <DecoratorSet decorators, typename BarrierSetT> 124 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap_at(oop base, ptrdiff_t offset) { 125 oop* const addr = field_addr(base, offset); 126 const oop o = Raw::oop_load_in_heap(addr); 127 128 if (HasDecorator<decorators, ON_UNKNOWN_OOP_REF>::value) { 129 return load_barrier_on_unknown_oop_field_preloaded(base, offset, addr, o); 130 } 131 132 return load_barrier_on_oop_field_preloaded(addr, o); 133 } 134 135 template <DecoratorSet decorators, typename BarrierSetT> 136 template <typename T> 137 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(T* addr, oop compare_value, oop new_value) { 138 verify_decorators_present<ON_STRONG_OOP_REF>(); 139 verify_decorators_absent<AS_NO_KEEPALIVE>(); 140 141 XBarrier::load_barrier_on_oop_field(addr); 142 return Raw::oop_atomic_cmpxchg_in_heap(addr, compare_value, new_value); 143 } 144 145 template <DecoratorSet decorators, typename BarrierSetT> 146 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_at(oop base, ptrdiff_t offset, oop compare_value, oop new_value) { 147 verify_decorators_present<ON_STRONG_OOP_REF | ON_UNKNOWN_OOP_REF>(); 148 verify_decorators_absent<AS_NO_KEEPALIVE>(); 149 150 // Through Unsafe.CompareAndExchangeObject()/CompareAndSetObject() we can receive 151 // calls with ON_UNKNOWN_OOP_REF set. However, we treat these as ON_STRONG_OOP_REF, 152 // with the motivation that if you're doing Unsafe operations on a Reference.referent 153 // field, then you're on your own anyway. 154 XBarrier::load_barrier_on_oop_field(field_addr(base, offset)); 155 return Raw::oop_atomic_cmpxchg_in_heap_at(base, offset, compare_value, new_value); 156 } 157 158 template <DecoratorSet decorators, typename BarrierSetT> 159 template <typename T> 160 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(T* addr, oop new_value) { 161 verify_decorators_present<ON_STRONG_OOP_REF>(); 162 verify_decorators_absent<AS_NO_KEEPALIVE>(); 163 164 const oop o = Raw::oop_atomic_xchg_in_heap(addr, new_value); 165 return XBarrier::load_barrier_on_oop(o); 166 } 167 168 template <DecoratorSet decorators, typename BarrierSetT> 169 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_at(oop base, ptrdiff_t offset, oop new_value) { 170 verify_decorators_present<ON_STRONG_OOP_REF>(); 171 verify_decorators_absent<AS_NO_KEEPALIVE>(); 172 173 const oop o = Raw::oop_atomic_xchg_in_heap_at(base, offset, new_value); 174 return XBarrier::load_barrier_on_oop(o); 175 } 176 177 template <DecoratorSet decorators, typename BarrierSetT> 178 template <typename T> 179 inline void XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, 180 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, 181 size_t length) { 182 T* src = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); 183 T* dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); 184 185 if ((!HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) && 186 (!HasDecorator<decorators, ARRAYCOPY_NOTNULL>::value)) { 187 // No check cast, bulk barrier and bulk copy 188 XBarrier::load_barrier_on_oop_array(src, length); 189 Raw::oop_arraycopy_in_heap(nullptr, 0, src, nullptr, 0, dst, length); 190 return; 191 } 192 193 // Check cast and copy each elements 194 Klass* const dst_klass = objArrayOop(dst_obj)->element_klass(); 195 for (const T* const end = src + length; src < end; src++, dst++) { 196 const oop elem = XBarrier::load_barrier_on_oop_field(src); 197 if (HasDecorator<decorators, ARRAYCOPY_NOTNULL>::value && elem == nullptr) { 198 throw_array_null_pointer_store_exception(src_obj, dst_obj, JavaThread::current()); 199 return; 200 } 201 if (HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value && 202 (!oopDesc::is_instanceof_or_null(elem, dst_klass))) { 203 // Check cast failed 204 throw_array_store_exception(src_obj, dst_obj, JavaThread::current()); 205 return; 206 } 207 208 // Cast is safe, since we know it's never a narrowOop 209 *(oop*)dst = elem; 210 } 211 } 212 213 template <DecoratorSet decorators, typename BarrierSetT> 214 inline void XBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) { 215 XBarrier::load_barrier_on_oop_fields(src); 216 Raw::clone_in_heap(src, dst, size); 217 } 218 219 template <DecoratorSet decorators, typename BarrierSetT> 220 inline void XBarrierSet::AccessBarrier<decorators, BarrierSetT>::value_copy_in_heap(void* src, void* dst, InlineKlass* md, LayoutKind lk) { 221 if (md->contains_oops()) { 222 // src/dst aren't oops, need offset to adjust oop map offset 223 const address src_oop_addr_offset = ((address) src) - md->first_field_offset(); 224 225 OopMapBlock* map = md->start_of_nonstatic_oop_maps(); 226 OopMapBlock* const end = map + md->nonstatic_oop_map_count(); 227 while (map != end) { 228 address soop_address = src_oop_addr_offset + map->offset(); 229 XBarrier::load_barrier_on_oop_array((oop*) soop_address, map->count()); 230 map++; 231 } 232 } 233 Raw::value_copy_in_heap(src, dst, md, lk); 234 } 235 236 // 237 // Not in heap 238 // 239 template <DecoratorSet decorators, typename BarrierSetT> 240 template <typename T> 241 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(T* addr) { 242 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 243 244 const oop o = Raw::oop_load_not_in_heap(addr); 245 return load_barrier_on_oop_field_preloaded(addr, o); 246 } 247 248 template <DecoratorSet decorators, typename BarrierSetT> 249 template <typename T> 250 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_not_in_heap(T* addr, oop compare_value, oop new_value) { 251 verify_decorators_present<ON_STRONG_OOP_REF>(); 252 verify_decorators_absent<AS_NO_KEEPALIVE>(); 253 254 return Raw::oop_atomic_cmpxchg_not_in_heap(addr, compare_value, new_value); 255 } 256 257 template <DecoratorSet decorators, typename BarrierSetT> 258 template <typename T> 259 inline oop XBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_not_in_heap(T* addr, oop new_value) { 260 verify_decorators_present<ON_STRONG_OOP_REF>(); 261 verify_decorators_absent<AS_NO_KEEPALIVE>(); 262 263 return Raw::oop_atomic_xchg_not_in_heap(addr, new_value); 264 } 265 266 #endif // SHARE_GC_X_XBARRIERSET_INLINE_HPP