1 /* 2 * Copyright (c) 2017, 2025, 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_Z_ZBARRIERSET_INLINE_HPP 25 #define SHARE_GC_Z_ZBARRIERSET_INLINE_HPP 26 27 #include "gc/z/zAddress.hpp" 28 #include "gc/z/zBarrierSet.hpp" 29 30 #include "gc/shared/accessBarrierSupport.inline.hpp" 31 #include "gc/z/zAddress.inline.hpp" 32 #include "gc/z/zBarrier.inline.hpp" 33 #include "gc/z/zIterator.inline.hpp" 34 #include "gc/z/zNMethod.hpp" 35 #include "memory/iterator.inline.hpp" 36 #include "oops/inlineKlass.inline.hpp" 37 #include "utilities/debug.hpp" 38 #include "utilities/copy.hpp" 39 40 template <DecoratorSet decorators, typename BarrierSetT> 41 template <DecoratorSet expected> 42 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_present() { 43 if ((decorators & expected) == 0) { 44 fatal("Using unsupported access decorators"); 45 } 46 } 47 48 template <DecoratorSet decorators, typename BarrierSetT> 49 template <DecoratorSet expected> 50 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_absent() { 51 if ((decorators & expected) != 0) { 52 fatal("Using unsupported access decorators"); 53 } 54 } 55 56 template <DecoratorSet decorators, typename BarrierSetT> 57 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::unsupported() { 58 ShouldNotReachHere(); 59 } 60 61 template <DecoratorSet decorators, typename BarrierSetT> 62 inline zpointer* ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::field_addr(oop base, ptrdiff_t offset) { 63 assert(base != nullptr, "Invalid base"); 64 return reinterpret_cast<zpointer*>(reinterpret_cast<intptr_t>((void*)base) + offset); 65 } 66 67 template <DecoratorSet decorators, typename BarrierSetT> 68 inline zaddress ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::load_barrier(zpointer* p, zpointer o) { 69 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 70 71 if (HasDecorator<decorators, AS_NO_KEEPALIVE>::value) { 72 if (HasDecorator<decorators, ON_STRONG_OOP_REF>::value) { 73 // Load barriers on strong oop refs don't keep objects alive 74 return ZBarrier::load_barrier_on_oop_field_preloaded(p, o); 75 } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) { 76 return ZBarrier::no_keep_alive_load_barrier_on_weak_oop_field_preloaded(p, o); 77 } else { 78 assert((HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value), "Must be"); 79 return ZBarrier::no_keep_alive_load_barrier_on_phantom_oop_field_preloaded(p, o); 80 } 81 } else { 82 if (HasDecorator<decorators, ON_STRONG_OOP_REF>::value) { 83 return ZBarrier::load_barrier_on_oop_field_preloaded(p, o); 84 } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) { 85 return ZBarrier::load_barrier_on_weak_oop_field_preloaded(p, o); 86 } else { 87 assert((HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value), "Must be"); 88 return ZBarrier::load_barrier_on_phantom_oop_field_preloaded(p, o); 89 } 90 } 91 } 92 93 template <DecoratorSet decorators, typename BarrierSetT> 94 inline zaddress ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::load_barrier_on_unknown_oop_ref(oop base, ptrdiff_t offset, zpointer* p, zpointer o) { 95 verify_decorators_present<ON_UNKNOWN_OOP_REF>(); 96 97 const DecoratorSet decorators_known_strength = 98 AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset); 99 100 if (HasDecorator<decorators, AS_NO_KEEPALIVE>::value) { 101 if (decorators_known_strength & ON_STRONG_OOP_REF) { 102 // Load barriers on strong oop refs don't keep objects alive 103 return ZBarrier::load_barrier_on_oop_field_preloaded(p, o); 104 } else if (decorators_known_strength & ON_WEAK_OOP_REF) { 105 return ZBarrier::no_keep_alive_load_barrier_on_weak_oop_field_preloaded(p, o); 106 } else { 107 assert(decorators_known_strength & ON_PHANTOM_OOP_REF, "Must be"); 108 return ZBarrier::no_keep_alive_load_barrier_on_phantom_oop_field_preloaded(p, o); 109 } 110 } else { 111 if (decorators_known_strength & ON_STRONG_OOP_REF) { 112 return ZBarrier::load_barrier_on_oop_field_preloaded(p, o); 113 } else if (decorators_known_strength & ON_WEAK_OOP_REF) { 114 return ZBarrier::load_barrier_on_weak_oop_field_preloaded(p, o); 115 } else { 116 assert(decorators_known_strength & ON_PHANTOM_OOP_REF, "Must be"); 117 return ZBarrier::load_barrier_on_phantom_oop_field_preloaded(p, o); 118 } 119 } 120 } 121 122 inline zpointer ZBarrierSet::store_good(oop obj) { 123 assert(ZPointerStoreGoodMask != 0, "sanity"); 124 125 const zaddress addr = to_zaddress(obj); 126 return ZAddress::store_good(addr); 127 } 128 129 template <DecoratorSet decorators, typename BarrierSetT> 130 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::store_barrier_heap_with_healing(zpointer* p) { 131 if (!HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value) { 132 ZBarrier::store_barrier_on_heap_oop_field(p, true /* heal */); 133 } else { 134 assert(false, "Should not be used on uninitialized memory"); 135 } 136 } 137 138 template <DecoratorSet decorators, typename BarrierSetT> 139 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::store_barrier_heap_without_healing(zpointer* p) { 140 if (!HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value) { 141 ZBarrier::store_barrier_on_heap_oop_field(p, false /* heal */); 142 } 143 } 144 145 template <DecoratorSet decorators, typename BarrierSetT> 146 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::no_keep_alive_store_barrier_heap(zpointer* p) { 147 if (!HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value) { 148 ZBarrier::no_keep_alive_store_barrier_on_heap_oop_field(p); 149 } 150 } 151 152 template <DecoratorSet decorators, typename BarrierSetT> 153 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::store_barrier_native_with_healing(zpointer* p) { 154 if (!HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value) { 155 ZBarrier::store_barrier_on_native_oop_field(p, true /* heal */); 156 } else { 157 assert(false, "Should not be used on uninitialized memory"); 158 } 159 } 160 161 template <DecoratorSet decorators, typename BarrierSetT> 162 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::store_barrier_native_without_healing(zpointer* p) { 163 if (!HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value) { 164 ZBarrier::store_barrier_on_native_oop_field(p, false /* heal */); 165 } 166 } 167 168 // 169 // In heap 170 // 171 template <DecoratorSet decorators, typename BarrierSetT> 172 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap(zpointer* p) { 173 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 174 175 const zpointer o = Raw::load_in_heap(p); 176 assert_is_valid(o); 177 178 return to_oop(load_barrier(p, o)); 179 } 180 181 template <DecoratorSet decorators, typename BarrierSetT> 182 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap_at(oop base, ptrdiff_t offset) { 183 zpointer* const p = field_addr(base, offset); 184 185 const zpointer o = Raw::load_in_heap(p); 186 assert_is_valid(o); 187 188 if (HasDecorator<decorators, ON_UNKNOWN_OOP_REF>::value) { 189 return to_oop(load_barrier_on_unknown_oop_ref(base, offset, p, o)); 190 } 191 192 return to_oop(load_barrier(p, o)); 193 } 194 195 template <DecoratorSet decorators> 196 bool is_store_barrier_no_keep_alive() { 197 if (HasDecorator<decorators, ON_STRONG_OOP_REF>::value) { 198 return HasDecorator<decorators, AS_NO_KEEPALIVE>::value; 199 } 200 201 if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) { 202 return true; 203 } 204 205 assert((decorators & ON_PHANTOM_OOP_REF) != 0, "Must be"); 206 return true; 207 } 208 209 template <DecoratorSet decorators> 210 inline bool is_store_barrier_no_keep_alive(oop base, ptrdiff_t offset) { 211 if (!HasDecorator<decorators, ON_UNKNOWN_OOP_REF>::value) { 212 return is_store_barrier_no_keep_alive<decorators>(); 213 } 214 215 const DecoratorSet decorators_known_strength = 216 AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset); 217 218 if ((decorators_known_strength & ON_STRONG_OOP_REF) != 0) { 219 return (decorators & AS_NO_KEEPALIVE) != 0; 220 } 221 222 if ((decorators_known_strength & ON_WEAK_OOP_REF) != 0) { 223 return true; 224 } 225 226 assert((decorators_known_strength & ON_PHANTOM_OOP_REF) != 0, "Must be"); 227 return true; 228 } 229 230 template <DecoratorSet decorators, typename BarrierSetT> 231 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_in_heap(zpointer* p, oop value) { 232 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 233 234 if (is_store_barrier_no_keep_alive<decorators>()) { 235 no_keep_alive_store_barrier_heap(p); 236 } else { 237 store_barrier_heap_without_healing(p); 238 } 239 240 Raw::store_in_heap(p, store_good(value)); 241 } 242 243 template <DecoratorSet decorators, typename BarrierSetT> 244 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) { 245 zpointer* const p = field_addr(base, offset); 246 247 if (is_store_barrier_no_keep_alive<decorators>(base, offset)) { 248 no_keep_alive_store_barrier_heap(p); 249 } else { 250 store_barrier_heap_without_healing(p); 251 } 252 253 Raw::store_in_heap(p, store_good(value)); 254 } 255 256 template <DecoratorSet decorators, typename BarrierSetT> 257 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_not_in_heap(zpointer* p, oop value) { 258 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 259 260 if (!is_store_barrier_no_keep_alive<decorators>()) { 261 store_barrier_native_without_healing(p); 262 } 263 264 Raw::store(p, store_good(value)); 265 } 266 267 template <DecoratorSet decorators, typename BarrierSetT> 268 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(zpointer* p, oop compare_value, oop new_value) { 269 verify_decorators_present<ON_STRONG_OOP_REF>(); 270 verify_decorators_absent<AS_NO_KEEPALIVE>(); 271 272 store_barrier_heap_with_healing(p); 273 274 const zpointer o = Raw::atomic_cmpxchg_in_heap(p, store_good(compare_value), store_good(new_value)); 275 assert_is_valid(o); 276 277 return to_oop(ZPointer::uncolor_store_good(o)); 278 } 279 280 template <DecoratorSet decorators, typename BarrierSetT> 281 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_at(oop base, ptrdiff_t offset, oop compare_value, oop new_value) { 282 verify_decorators_present<ON_STRONG_OOP_REF | ON_UNKNOWN_OOP_REF>(); 283 verify_decorators_absent<AS_NO_KEEPALIVE>(); 284 285 // Through Unsafe.CompareAndExchangeObject()/CompareAndSetObject() we can receive 286 // calls with ON_UNKNOWN_OOP_REF set. However, we treat these as ON_STRONG_OOP_REF, 287 // with the motivation that if you're doing Unsafe operations on a Reference.referent 288 // field, then you're on your own anyway. 289 zpointer* const p = field_addr(base, offset); 290 291 store_barrier_heap_with_healing(p); 292 293 const zpointer o = Raw::atomic_cmpxchg_in_heap(p, store_good(compare_value), store_good(new_value)); 294 assert_is_valid(o); 295 296 return to_oop(ZPointer::uncolor_store_good(o)); 297 } 298 299 template <DecoratorSet decorators, typename BarrierSetT> 300 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(zpointer* p, oop new_value) { 301 verify_decorators_present<ON_STRONG_OOP_REF>(); 302 verify_decorators_absent<AS_NO_KEEPALIVE>(); 303 304 store_barrier_heap_with_healing(p); 305 306 const zpointer o = Raw::atomic_xchg_in_heap(p, store_good(new_value)); 307 assert_is_valid(o); 308 309 return to_oop(ZPointer::uncolor_store_good(o)); 310 } 311 312 template <DecoratorSet decorators, typename BarrierSetT> 313 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_at(oop base, ptrdiff_t offset, oop new_value) { 314 verify_decorators_present<ON_STRONG_OOP_REF>(); 315 verify_decorators_absent<AS_NO_KEEPALIVE>(); 316 317 zpointer* const p = field_addr(base, offset); 318 319 store_barrier_heap_with_healing(p); 320 321 const zpointer o = Raw::atomic_xchg_in_heap(p, store_good(new_value)); 322 assert_is_valid(o); 323 324 return to_oop(ZPointer::uncolor_store_good(o)); 325 } 326 327 template <DecoratorSet decorators, typename BarrierSetT> 328 inline zaddress ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one_barriers(zpointer* dst, zpointer* src) { 329 store_barrier_heap_without_healing(dst); 330 331 return ZBarrier::load_barrier_on_oop_field(src); 332 } 333 334 template <DecoratorSet decorators, typename BarrierSetT> 335 inline ZBarrierSet::OopCopyCheckStatus ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one(zpointer* dst, zpointer* src) { 336 const zaddress obj = oop_copy_one_barriers(dst, src); 337 338 if (HasDecorator<decorators, ARRAYCOPY_NOTNULL>::value && is_null(obj)) { 339 return oop_copy_check_null; 340 } 341 342 Atomic::store(dst, ZAddress::store_good(obj)); 343 return oop_copy_check_ok; 344 } 345 346 template <DecoratorSet decorators, typename BarrierSetT> 347 inline ZBarrierSet::OopCopyCheckStatus ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one_check_cast(zpointer* dst, zpointer* src, Klass* dst_klass) { 348 const zaddress obj = oop_copy_one_barriers(dst, src); 349 const bool null_check = HasDecorator<decorators, ARRAYCOPY_NOTNULL>::value; 350 351 if (null_check && is_null(obj)) { 352 return oop_copy_check_null; 353 } 354 else if (!oopDesc::is_instanceof_or_null(to_oop(obj), dst_klass)) { 355 // Check cast failed 356 return oop_copy_check_class_cast; 357 } 358 359 Atomic::store(dst, ZAddress::store_good(obj)); 360 361 return oop_copy_check_ok; 362 } 363 364 365 template <DecoratorSet decorators, typename BarrierSetT> 366 inline ZBarrierSet::OopCopyCheckStatus ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap_check_cast(zpointer* dst, zpointer* src, size_t length, Klass* dst_klass) { 367 // Check cast and copy each elements 368 OopCopyCheckStatus check_status = oop_copy_check_ok; 369 for (const zpointer* const end = src + length; (check_status == oop_copy_check_ok) && (src < end); src++, dst++) { 370 check_status = oop_copy_one_check_cast(dst, src, dst_klass); 371 } 372 return check_status; 373 } 374 375 template <DecoratorSet decorators, typename BarrierSetT> 376 inline ZBarrierSet::OopCopyCheckStatus ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap_no_check_cast(zpointer* dst, zpointer* src, size_t length) { 377 const bool is_disjoint = HasDecorator<decorators, ARRAYCOPY_DISJOINT>::value; 378 OopCopyCheckStatus check_status = oop_copy_check_ok; 379 if (is_disjoint || src > dst) { 380 for (const zpointer* const end = src + length; (check_status == oop_copy_check_ok) && (src < end); src++, dst++) { 381 check_status = oop_copy_one(dst, src); 382 } 383 return check_status; 384 } 385 386 if (src < dst) { 387 const zpointer* const end = src; 388 src += length - 1; 389 dst += length - 1; 390 for ( ; (check_status == oop_copy_check_ok) && (src >= end); src--, dst--) { 391 check_status = oop_copy_one(dst, src); 392 } 393 return check_status; 394 } 395 396 // src and dst are the same; nothing to do 397 return check_status; 398 } 399 400 template <DecoratorSet decorators, typename BarrierSetT> 401 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, zpointer* src_raw, 402 arrayOop dst_obj, size_t dst_offset_in_bytes, zpointer* dst_raw, 403 size_t length) { 404 zpointer* const src = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); 405 zpointer* const dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); 406 OopCopyCheckStatus check_status; 407 408 if (HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) { 409 Klass* const dst_klass = objArrayOop(dst_obj)->element_klass(); 410 check_status = oop_arraycopy_in_heap_check_cast(dst, src, length, dst_klass); 411 } else { 412 check_status = oop_arraycopy_in_heap_no_check_cast(dst, src, length); 413 } 414 415 switch (check_status) { 416 case oop_copy_check_ok: 417 return; 418 case oop_copy_check_class_cast: 419 throw_array_store_exception(src_obj, dst_obj, JavaThread::current()); 420 break; 421 case oop_copy_check_null: 422 throw_array_null_pointer_store_exception(src_obj, dst_obj, JavaThread::current()); 423 break; 424 default: 425 ShouldNotReachHere(); 426 return; 427 } 428 } 429 430 class ZColorStoreGoodOopClosure : public BasicOopIterateClosure { 431 public: 432 virtual void do_oop(oop* p_) { 433 volatile zpointer* const p = (volatile zpointer*)p_; 434 const zpointer ptr = ZBarrier::load_atomic(p); 435 const zaddress addr = ZPointer::uncolor(ptr); 436 Atomic::store(p, ZAddress::store_good(addr)); 437 } 438 439 virtual void do_oop(narrowOop* p) { 440 ShouldNotReachHere(); 441 } 442 }; 443 444 class ZLoadBarrierOopClosure : public BasicOopIterateClosure { 445 public: 446 virtual void do_oop(oop* p) { 447 ZBarrier::load_barrier_on_oop_field((zpointer*)p); 448 } 449 450 virtual void do_oop(narrowOop* p) { 451 ShouldNotReachHere(); 452 } 453 }; 454 455 template <DecoratorSet decorators, typename BarrierSetT> 456 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) { 457 check_is_valid_zaddress(src); 458 459 if (dst->is_objArray()) { 460 // Cloning an object array is similar to performing array copy. 461 // If an array is large enough to have its allocation segmented, 462 // this operation might require GC barriers. However, the intrinsics 463 // for cloning arrays transform the clone to an optimized allocation 464 // and arraycopy sequence, so the performance of this runtime call 465 // does not matter for object arrays. 466 clone_obj_array(objArrayOop(src), objArrayOop(dst)); 467 return; 468 } 469 470 // Fix the oops 471 ZLoadBarrierOopClosure cl; 472 ZIterator::oop_iterate(src, &cl); 473 474 // Clone the object 475 Raw::clone_in_heap(src, dst, size); 476 477 assert(dst->is_typeArray() || ZHeap::heap()->is_young(to_zaddress(dst)), "ZColorStoreGoodOopClosure is only valid for young objects"); 478 479 // Color store good before handing out 480 ZColorStoreGoodOopClosure cl_sg; 481 ZIterator::oop_iterate(dst, &cl_sg); 482 } 483 484 static inline void copy_primitive_payload(const void* src, const void* dst, const size_t payload_size_bytes, size_t& copied_bytes) { 485 if (payload_size_bytes == 0) { 486 return; 487 } 488 void* src_payload = (void*)(address(src) + copied_bytes); 489 void* dst_payload = (void*)(address(dst) + copied_bytes); 490 Copy::copy_value_content(src_payload, dst_payload, payload_size_bytes); 491 copied_bytes += payload_size_bytes; 492 } 493 494 template <DecoratorSet decorators, typename BarrierSetT> 495 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::value_copy_in_heap(void* src, void* dst, InlineKlass* md, LayoutKind lk) { 496 if (md->contains_oops()) { 497 // Iterate over each oop map, performing: 498 // 1) possibly raw copy for any primitive payload before each map 499 // 2) load and store barrier for each oop 500 // 3) possibly raw copy for any primitive payload trailer 501 502 // src/dst may not be oops, need offset to adjust oop map offset 503 const address src_oop_addr_offset = ((address) src) - md->payload_offset(); 504 OopMapBlock* map = md->start_of_nonstatic_oop_maps(); 505 const OopMapBlock* const end = map + md->nonstatic_oop_map_count(); 506 size_t size_in_bytes = md->layout_size_in_bytes(lk); 507 size_t copied_bytes = 0; 508 while (map != end) { 509 zpointer *src_p = (zpointer*)(src_oop_addr_offset + map->offset()); 510 const uintptr_t oop_offset = uintptr_t(src_p) - uintptr_t(src); 511 zpointer *dst_p = (zpointer*)(uintptr_t(dst) + oop_offset); 512 513 // Copy any leading primitive payload before every cluster of oops 514 assert(copied_bytes < oop_offset || copied_bytes == oop_offset, "Negative sized leading payload segment"); 515 copy_primitive_payload(src, dst, oop_offset - copied_bytes, copied_bytes); 516 517 // Copy a cluster of oops 518 for (const zpointer* const src_end = src_p + map->count(); src_p < src_end; src_p++, dst_p++) { 519 oop_copy_one(dst_p, src_p); 520 copied_bytes += sizeof(zpointer); 521 } 522 map++; 523 } 524 525 // Copy trailing primitive payload after potential oops 526 assert(copied_bytes < size_in_bytes || copied_bytes == size_in_bytes, "Negative sized trailing payload segment"); 527 copy_primitive_payload(src, dst, size_in_bytes - copied_bytes, copied_bytes); 528 } else { 529 Raw::value_copy_in_heap(src, dst, md, lk); 530 } 531 } 532 533 // 534 // Not in heap 535 // 536 template <DecoratorSet decorators, typename BarrierSetT> 537 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(zpointer* p) { 538 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 539 540 const zpointer o = Raw::template load<zpointer>(p); 541 assert_is_valid(o); 542 return to_oop(load_barrier(p, o)); 543 } 544 545 template <DecoratorSet decorators, typename BarrierSetT> 546 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(oop* p) { 547 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); 548 549 return oop_load_not_in_heap((zpointer*)p); 550 } 551 552 template <DecoratorSet decorators, typename BarrierSetT> 553 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_not_in_heap(zpointer* p, oop compare_value, oop new_value) { 554 verify_decorators_present<ON_STRONG_OOP_REF>(); 555 verify_decorators_absent<AS_NO_KEEPALIVE>(); 556 557 store_barrier_native_with_healing(p); 558 559 const zpointer o = Raw::atomic_cmpxchg(p, store_good(compare_value), store_good(new_value)); 560 assert_is_valid(o); 561 562 return to_oop(ZPointer::uncolor_store_good(o)); 563 } 564 565 template <DecoratorSet decorators, typename BarrierSetT> 566 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_not_in_heap(zpointer* p, oop new_value) { 567 verify_decorators_present<ON_STRONG_OOP_REF>(); 568 verify_decorators_absent<AS_NO_KEEPALIVE>(); 569 570 store_barrier_native_with_healing(p); 571 572 const zpointer o = Raw::atomic_xchg(p, store_good(new_value)); 573 assert_is_valid(o); 574 575 return to_oop(ZPointer::uncolor_store_good(o)); 576 } 577 578 #endif // SHARE_GC_Z_ZBARRIERSET_INLINE_HPP