< prev index next >

src/hotspot/share/gc/z/zBarrierSet.inline.hpp

Print this page

 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/zBarrierSet.hpp"
 28 
 29 #include "gc/shared/accessBarrierSupport.inline.hpp"

 30 #include "gc/z/zAddress.inline.hpp"
 31 #include "gc/z/zHeap.hpp"
 32 #include "gc/z/zNMethod.hpp"
 33 #include "gc/z/zUtils.inline.hpp"

 34 #include "oops/objArrayOop.hpp"

 35 #include "utilities/debug.hpp"

 36 
 37 template <DecoratorSet decorators, typename BarrierSetT>
 38 template <DecoratorSet expected>
 39 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_present() {
 40   if ((decorators & expected) == 0) {
 41     fatal("Using unsupported access decorators");
 42   }
 43 }
 44 
 45 template <DecoratorSet decorators, typename BarrierSetT>
 46 template <DecoratorSet expected>
 47 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_absent() {
 48   if ((decorators & expected) != 0) {
 49     fatal("Using unsupported access decorators");
 50   }
 51 }
 52 
 53 template <DecoratorSet decorators, typename BarrierSetT>
 54 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::unsupported() {
 55   ShouldNotReachHere();

315 
316   store_barrier_heap_with_healing(p);
317 
318   const zpointer o = Raw::atomic_xchg_in_heap(p, store_good(new_value));
319   assert_is_valid(o);
320 
321   return to_oop(ZPointer::uncolor_store_good(o));
322 }
323 
324 template <DecoratorSet decorators, typename BarrierSetT>
325 inline zaddress ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one_barriers(zpointer* dst, zpointer* src) {
326   store_barrier_heap_without_healing(dst);
327 
328   return ZBarrierSet::load_barrier_on_oop_field(src);
329 }
330 
331 template <DecoratorSet decorators, typename BarrierSetT>
332 inline OopCopyResult ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one(zpointer* dst, zpointer* src) {
333   const zaddress obj = oop_copy_one_barriers(dst, src);
334 
335   // Future location for null-restriction check and failure reporting


336 
337   AtomicAccess::store(dst, ZAddress::store_good(obj));
338 
339   return OopCopyResult::ok;
340 }
341 















342 template <DecoratorSet decorators, typename BarrierSetT>
343 inline OopCopyResult ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one_check_cast(zpointer* dst, zpointer* src, Klass* dst_klass) {
344   const zaddress obj = oop_copy_one_barriers(dst, src);
345 




346   if (!oopDesc::is_instanceof_or_null(to_oop(obj), dst_klass)) {
347     // Check cast failed
348     return OopCopyResult::failed_check_class_cast;
349   }
350 
351   AtomicAccess::store(dst, ZAddress::store_good(obj));
352 
353   return OopCopyResult::ok;
354 }
355 
356 template <DecoratorSet decorators, typename BarrierSetT>
357 inline OopCopyResult ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap_check_cast(zpointer* dst, zpointer* src, size_t length, Klass* dst_klass) {
358   // Check cast and copy each elements
359   for (const zpointer* const end = src + length; src < end; src++, dst++) {
360     const OopCopyResult result = oop_copy_one_check_cast(dst, src, dst_klass);
361     if (result != OopCopyResult::ok) {
362       return result;
363     }
364   }
365 

406   zpointer* const src = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw);
407   zpointer* const dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw);
408 
409   if (HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) {
410     Klass* const dst_klass = objArrayOop(dst_obj)->element_klass();
411     return oop_arraycopy_in_heap_check_cast(dst, src, length, dst_klass);
412   } else {
413     return oop_arraycopy_in_heap_no_check_cast(dst, src, length);
414   }
415 }
416 
417 template <DecoratorSet decorators, typename BarrierSetT>
418 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
419   check_is_valid_zaddress(src);
420   check_is_valid_zaddress(dst);
421   precond(src->klass() == dst->klass());
422 
423   clone_obj(to_zaddress(src), to_zaddress(dst), ZUtils::words_to_bytes(size));
424 }
425 

























































































































426 //
427 // Not in heap
428 //
429 template <DecoratorSet decorators, typename BarrierSetT>
430 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(zpointer* p) {
431   verify_decorators_absent<ON_UNKNOWN_OOP_REF>();
432 
433   const zpointer o = Raw::template load<zpointer>(p);
434   assert_is_valid(o);
435   return to_oop(load_barrier(p, o));
436 }
437 
438 template <DecoratorSet decorators, typename BarrierSetT>
439 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(oop* p) {
440   verify_decorators_absent<ON_UNKNOWN_OOP_REF>();
441 
442   return oop_load_not_in_heap((zpointer*)p);
443 }
444 
445 template <DecoratorSet decorators, typename BarrierSetT>

 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/zBarrierSet.hpp"
 28 
 29 #include "gc/shared/accessBarrierSupport.inline.hpp"
 30 #include "gc/z/zAddress.hpp"
 31 #include "gc/z/zAddress.inline.hpp"
 32 #include "gc/z/zHeap.hpp"
 33 #include "gc/z/zNMethod.hpp"
 34 #include "gc/z/zUtils.inline.hpp"
 35 #include "oops/inlineKlass.inline.hpp"
 36 #include "oops/objArrayOop.hpp"
 37 #include "utilities/copy.hpp"
 38 #include "utilities/debug.hpp"
 39 #include "utilities/globalDefinitions.hpp"
 40 
 41 template <DecoratorSet decorators, typename BarrierSetT>
 42 template <DecoratorSet expected>
 43 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_present() {
 44   if ((decorators & expected) == 0) {
 45     fatal("Using unsupported access decorators");
 46   }
 47 }
 48 
 49 template <DecoratorSet decorators, typename BarrierSetT>
 50 template <DecoratorSet expected>
 51 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_absent() {
 52   if ((decorators & expected) != 0) {
 53     fatal("Using unsupported access decorators");
 54   }
 55 }
 56 
 57 template <DecoratorSet decorators, typename BarrierSetT>
 58 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::unsupported() {
 59   ShouldNotReachHere();

319 
320   store_barrier_heap_with_healing(p);
321 
322   const zpointer o = Raw::atomic_xchg_in_heap(p, store_good(new_value));
323   assert_is_valid(o);
324 
325   return to_oop(ZPointer::uncolor_store_good(o));
326 }
327 
328 template <DecoratorSet decorators, typename BarrierSetT>
329 inline zaddress ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one_barriers(zpointer* dst, zpointer* src) {
330   store_barrier_heap_without_healing(dst);
331 
332   return ZBarrierSet::load_barrier_on_oop_field(src);
333 }
334 
335 template <DecoratorSet decorators, typename BarrierSetT>
336 inline OopCopyResult ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one(zpointer* dst, zpointer* src) {
337   const zaddress obj = oop_copy_one_barriers(dst, src);
338 
339   if (HasDecorator<decorators, ARRAYCOPY_NOTNULL>::value && is_null(obj)) {
340     return OopCopyResult::failed_check_null;
341   }
342 
343   AtomicAccess::store(dst, ZAddress::store_good(obj));
344 
345   return OopCopyResult::ok;
346 }
347 
348 template <DecoratorSet decorators, typename BarrierSetT>
349 inline OopCopyResult ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_clear_one(zpointer* dst) {
350   if (HasDecorator<decorators, ARRAYCOPY_NOTNULL>::value) {
351     return OopCopyResult::failed_check_null;
352   }
353 
354   // Store barrier
355   store_barrier_heap_without_healing(dst);
356 
357   // Store colored null
358   AtomicAccess::store(dst, color_null());
359 
360   return OopCopyResult::ok;
361 }
362 
363 template <DecoratorSet decorators, typename BarrierSetT>
364 inline OopCopyResult ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_copy_one_check_cast(zpointer* dst, zpointer* src, Klass* dst_klass) {
365   const zaddress obj = oop_copy_one_barriers(dst, src);
366 
367   if (HasDecorator<decorators, ARRAYCOPY_NOTNULL>::value && is_null(obj)) {
368     return OopCopyResult::failed_check_null;
369   }
370 
371   if (!oopDesc::is_instanceof_or_null(to_oop(obj), dst_klass)) {
372     // Check cast failed
373     return OopCopyResult::failed_check_class_cast;
374   }
375 
376   AtomicAccess::store(dst, ZAddress::store_good(obj));
377 
378   return OopCopyResult::ok;
379 }
380 
381 template <DecoratorSet decorators, typename BarrierSetT>
382 inline OopCopyResult ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap_check_cast(zpointer* dst, zpointer* src, size_t length, Klass* dst_klass) {
383   // Check cast and copy each elements
384   for (const zpointer* const end = src + length; src < end; src++, dst++) {
385     const OopCopyResult result = oop_copy_one_check_cast(dst, src, dst_klass);
386     if (result != OopCopyResult::ok) {
387       return result;
388     }
389   }
390 

431   zpointer* const src = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw);
432   zpointer* const dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw);
433 
434   if (HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) {
435     Klass* const dst_klass = objArrayOop(dst_obj)->element_klass();
436     return oop_arraycopy_in_heap_check_cast(dst, src, length, dst_klass);
437   } else {
438     return oop_arraycopy_in_heap_no_check_cast(dst, src, length);
439   }
440 }
441 
442 template <DecoratorSet decorators, typename BarrierSetT>
443 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
444   check_is_valid_zaddress(src);
445   check_is_valid_zaddress(dst);
446   precond(src->klass() == dst->klass());
447 
448   clone_obj(to_zaddress(src), to_zaddress(dst), ZUtils::words_to_bytes(size));
449 }
450 
451 static inline void copy_primitive_payload(const void* src, const void* dst, const size_t payload_size_bytes, size_t& copied_bytes) {
452   if (payload_size_bytes == 0) {
453     return;
454   }
455 
456   void* src_payload = (void*)(address(src) + copied_bytes);
457   void* dst_payload = (void*)(address(dst) + copied_bytes);
458   Copy::copy_value_content(src_payload, dst_payload, payload_size_bytes);
459   copied_bytes += payload_size_bytes;
460 }
461 
462 static inline void clear_primitive_payload(const void* dst, const size_t payload_size_bytes, size_t& copied_bytes) {
463   if (payload_size_bytes == 0) {
464     return;
465   }
466 
467   void* dst_payload = (void*)(address(dst) + copied_bytes);
468   Copy::fill_to_memory_atomic(dst_payload, payload_size_bytes);
469   copied_bytes += payload_size_bytes;
470 }
471 
472 template <DecoratorSet decorators, typename BarrierSetT>
473 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::value_copy_in_heap(const ValuePayload& src, const ValuePayload& dst) {
474   precond(src.klass() == dst.klass());
475 
476   const LayoutKind lk = LayoutKindHelper::get_copy_layout(src.layout_kind(), dst.layout_kind());
477   const InlineKlass* md = src.klass();
478   if (md->contains_oops()) {
479     assert(!LayoutKindHelper::is_atomic_flat(lk) ||
480                (md->nonstatic_oop_map_count() == 1 &&
481                 md->layout_size_in_bytes(lk) == sizeof(zpointer)),
482            "ZGC can only handle atomic flat values with a single oop");
483 
484     // Iterate over each oop map, performing:
485     //   1) possibly raw copy for any primitive payload before each map
486     //   2) load and store barrier for each oop
487     //   3) possibly raw copy for any primitive payload trailer
488 
489     // addr() points at the payload start, the oop map offset are relative to
490     // the object header, adjust address to account for this discrepancy.
491     const address src_addr = src.addr();
492     const address dst_addr = dst.addr();
493     const address oop_map_adjusted_src_addr = src_addr - md->payload_offset();
494     OopMapBlock* map = md->start_of_nonstatic_oop_maps();
495     const OopMapBlock* const end = map + md->nonstatic_oop_map_count();
496     size_t size_in_bytes = md->layout_size_in_bytes(lk);
497     size_t copied_bytes = 0;
498     while (map != end) {
499       zpointer* src_p = (zpointer*)(oop_map_adjusted_src_addr + map->offset());
500       const uintptr_t oop_offset = uintptr_t(src_p) - uintptr_t(src_addr);
501       zpointer* dst_p = (zpointer*)(uintptr_t(dst_addr) + oop_offset);
502 
503       // Copy any leading primitive payload before every cluster of oops
504       assert(copied_bytes < oop_offset || copied_bytes == oop_offset, "Negative sized leading payload segment");
505       copy_primitive_payload(src_addr, dst_addr, oop_offset - copied_bytes, copied_bytes);
506 
507       // Copy a cluster of oops
508       for (const zpointer* const src_end = src_p + map->count(); src_p < src_end; src_p++, dst_p++) {
509         oop_copy_one(dst_p, src_p);
510         copied_bytes += sizeof(zpointer);
511       }
512       map++;
513     }
514 
515     // Copy trailing primitive payload after potential oops
516     assert(copied_bytes < size_in_bytes || copied_bytes == size_in_bytes, "Negative sized trailing payload segment");
517     copy_primitive_payload(src_addr, dst_addr, size_in_bytes - copied_bytes, copied_bytes);
518   } else {
519     Raw::value_copy_in_heap(src, dst);
520   }
521 }
522 
523 template <DecoratorSet decorators, typename BarrierSetT>
524 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::value_store_null_in_heap(const ValuePayload& dst) {
525   const LayoutKind lk = dst.layout_kind();
526   assert(!LayoutKindHelper::is_null_free_flat(lk), "Cannot store null in null free layout");
527   const InlineKlass* md = dst.klass();
528 
529   if (md->contains_oops()) {
530     assert(!LayoutKindHelper::is_atomic_flat(lk) ||
531                (md->nonstatic_oop_map_count() == 1 &&
532                 md->layout_size_in_bytes(lk) == sizeof(zpointer)),
533            "ZGC can only handle atomic flat values with a single oop");
534 
535     // Iterate over each oop map, performing:
536     //   1) possibly raw clear for any primitive payload before each map
537     //   2) store barrier and clear for each oop
538     //   3) possibly raw clear for any primitive payload trailer
539 
540     // addr() points at the payload start, the oop map offset are relative to
541     // the object header, adjust address to account for this discrepancy.
542     const address dst_addr = dst.addr();
543     const address oop_map_adjusted_dst_addr = dst_addr - md->payload_offset();
544     OopMapBlock* map = md->start_of_nonstatic_oop_maps();
545     const OopMapBlock* const end = map + md->nonstatic_oop_map_count();
546     size_t size_in_bytes = md->layout_size_in_bytes(lk);
547     size_t copied_bytes = 0;
548     while (map != end) {
549       zpointer* dst_p = (zpointer*)(oop_map_adjusted_dst_addr + map->offset());
550       const uintptr_t oop_offset = uintptr_t(dst_p) - uintptr_t(dst_addr);
551 
552       // Clear any leading primitive payload before every cluster of oops
553       assert(copied_bytes < oop_offset || copied_bytes == oop_offset, "Negative sized leading payload segment");
554       clear_primitive_payload(dst_addr, oop_offset - copied_bytes, copied_bytes);
555 
556       // Clear a cluster of oops
557       for (const zpointer* const dst_end = dst_p + map->count(); dst_p < dst_end; dst_p++) {
558         oop_clear_one(dst_p);
559         copied_bytes += sizeof(zpointer);
560       }
561       map++;
562     }
563 
564     // Clear trailing primitive payload after potential oops
565     assert(copied_bytes < size_in_bytes || copied_bytes == size_in_bytes, "Negative sized trailing payload segment");
566     clear_primitive_payload(dst_addr, size_in_bytes - copied_bytes, copied_bytes);
567   } else {
568     Raw::value_store_null(dst);
569   }
570 }
571 
572 //
573 // Not in heap
574 //
575 template <DecoratorSet decorators, typename BarrierSetT>
576 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(zpointer* p) {
577   verify_decorators_absent<ON_UNKNOWN_OOP_REF>();
578 
579   const zpointer o = Raw::template load<zpointer>(p);
580   assert_is_valid(o);
581   return to_oop(load_barrier(p, o));
582 }
583 
584 template <DecoratorSet decorators, typename BarrierSetT>
585 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(oop* p) {
586   verify_decorators_absent<ON_UNKNOWN_OOP_REF>();
587 
588   return oop_load_not_in_heap((zpointer*)p);
589 }
590 
591 template <DecoratorSet decorators, typename BarrierSetT>
< prev index next >