< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp

Print this page

150       !_heap->marking_context()->is_marked_strong(obj)) {
151     return nullptr;
152   }
153 
154   // Allow runtime to see unreachable objects that are visited during concurrent class-unloading.
155   if ((decorators & AS_NO_KEEPALIVE) != 0 &&
156       _heap->is_concurrent_weak_root_in_progress() &&
157       !_heap->marking_context()->is_marked(obj)) {
158     return obj;
159   }
160 
161   oop fwd = load_reference_barrier(obj);
162   if (load_addr != nullptr && fwd != obj) {
163     // Since we are here and we know the load address, update the reference.
164     ShenandoahHeap::atomic_update_oop(fwd, load_addr, obj);
165   }
166 
167   return fwd;
168 }
169 
170 inline void ShenandoahBarrierSet::enqueue(oop obj) {
171   assert(obj != nullptr, "checked by caller");

172   assert(_satb_mark_queue_set.is_active(), "only get here when SATB active");
173 
174   // Filter marked objects before hitting the SATB queues. The same predicate would
175   // be used by SATBMQ::filter to eliminate already marked objects downstream, but
176   // filtering here helps to avoid wasteful SATB queueing work to begin with.
177   if (!_heap->requires_marking(obj)) return;
178 
179   SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(Thread::current());
180   _satb_mark_queue_set.enqueue_known_active(queue, obj);
181 }
182 
183 template <DecoratorSet decorators, typename T>
184 inline void ShenandoahBarrierSet::satb_barrier(T *field) {
185   // Uninitialized and no-keepalive stores do not need barrier.
186   if (HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value ||
187       HasDecorator<decorators, AS_NO_KEEPALIVE>::value) {
188     return;
189   }
190 
191   // Stores to weak/phantom require no barrier. The original references would
192   // have been enqueued in the SATB buffer by the load barrier if they were needed.
193   if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value ||
194       HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value) {
195     return;
196   }
197 

417 
418   // Unsafe.getAndSet comes here with ON_UNKNOWN_OOP_REF set.
419   // These are normally strong refs, but one can use Unsafe on Reference.referent.
420   // We cannot deal with that case. If application does Unsafe operations on
421   // Reference.referent field, this likely breaks weak reference semantics already.
422   // We upgrade the access to strong in (sometimes futile) attempt to maintain heap
423   // integrity, and assert in debug builds for better diagnostics.
424   DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset);
425   assert((resolved_decorators & ON_STRONG_OOP_REF) != 0, "Application error: XCHG on weak location");
426   resolved_decorators = (resolved_decorators & ~ON_DECORATOR_MASK) | ON_STRONG_OOP_REF;
427 
428   auto addr = AccessInternal::oop_field_addr<decorators>(base, offset);
429   oop result = bs->oop_xchg(resolved_decorators, addr, new_value);
430   if (ShenandoahCardBarrier) {
431     bs->write_ref_field_post<decorators>(addr);
432   }
433   return result;
434 }
435 
436 // Clone barrier support


















































437 template <DecoratorSet decorators, typename BarrierSetT>
438 void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
439   if (ShenandoahCloneBarrier) {
440     ShenandoahBarrierSet::barrier_set()->clone_barrier_runtime(src);









441   }

442   Raw::clone(src, dst, size);




443 }
444 
445 template <DecoratorSet decorators, typename BarrierSetT>
446 template <typename T>
447 OopCopyResult ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
448                                                                                                   arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
449                                                                                                   size_t length) {
450   T* src = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw);
451   T* dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw);
452 
453   ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
454   bs->arraycopy_barrier(src, dst, length);
455   OopCopyResult result = Raw::oop_arraycopy_in_heap(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
456   if (ShenandoahCardBarrier) {
457     bs->write_ref_array((HeapWord*) dst, length);
458   }
459   return result;
460 }
461 
462 template <class T, bool HAS_FWD, bool EVAC, bool ENQUEUE>

150       !_heap->marking_context()->is_marked_strong(obj)) {
151     return nullptr;
152   }
153 
154   // Allow runtime to see unreachable objects that are visited during concurrent class-unloading.
155   if ((decorators & AS_NO_KEEPALIVE) != 0 &&
156       _heap->is_concurrent_weak_root_in_progress() &&
157       !_heap->marking_context()->is_marked(obj)) {
158     return obj;
159   }
160 
161   oop fwd = load_reference_barrier(obj);
162   if (load_addr != nullptr && fwd != obj) {
163     // Since we are here and we know the load address, update the reference.
164     ShenandoahHeap::atomic_update_oop(fwd, load_addr, obj);
165   }
166 
167   return fwd;
168 }
169 
170 inline void ShenandoahBarrierSet::enqueue(oop obj, bool filter) {
171   assert(obj != nullptr, "checked by caller");
172   shenandoah_assert_correct(nullptr, obj);
173   assert(_satb_mark_queue_set.is_active(), "only get here when SATB active");
174 
175   // Filter marked objects before hitting the SATB queues. The same predicate would
176   // be used by SATBMQ::filter to eliminate already marked objects downstream, but
177   // filtering here helps to avoid wasteful SATB queueing work to begin with.
178   if (filter && !_heap->requires_marking(obj)) return;
179 
180   SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(Thread::current());
181   _satb_mark_queue_set.enqueue_known_active(queue, obj);
182 }
183 
184 template <DecoratorSet decorators, typename T>
185 inline void ShenandoahBarrierSet::satb_barrier(T *field) {
186   // Uninitialized and no-keepalive stores do not need barrier.
187   if (HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value ||
188       HasDecorator<decorators, AS_NO_KEEPALIVE>::value) {
189     return;
190   }
191 
192   // Stores to weak/phantom require no barrier. The original references would
193   // have been enqueued in the SATB buffer by the load barrier if they were needed.
194   if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value ||
195       HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value) {
196     return;
197   }
198 

418 
419   // Unsafe.getAndSet comes here with ON_UNKNOWN_OOP_REF set.
420   // These are normally strong refs, but one can use Unsafe on Reference.referent.
421   // We cannot deal with that case. If application does Unsafe operations on
422   // Reference.referent field, this likely breaks weak reference semantics already.
423   // We upgrade the access to strong in (sometimes futile) attempt to maintain heap
424   // integrity, and assert in debug builds for better diagnostics.
425   DecoratorSet resolved_decorators = AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset);
426   assert((resolved_decorators & ON_STRONG_OOP_REF) != 0, "Application error: XCHG on weak location");
427   resolved_decorators = (resolved_decorators & ~ON_DECORATOR_MASK) | ON_STRONG_OOP_REF;
428 
429   auto addr = AccessInternal::oop_field_addr<decorators>(base, offset);
430   oop result = bs->oop_xchg(resolved_decorators, addr, new_value);
431   if (ShenandoahCardBarrier) {
432     bs->write_ref_field_post<decorators>(addr);
433   }
434   return result;
435 }
436 
437 // Clone barrier support
438 template <bool EVAC>
439 class ShenandoahUpdateEvacForCloneOopClosure : public BasicOopIterateClosure {
440 private:
441   ShenandoahHeap* const _heap;
442   const ShenandoahCollectionSet* const _cset;
443   Thread* const _thread;
444 
445   template <class T>
446   inline void do_oop_work(T* p) {
447     T o = RawAccess<>::oop_load(p);
448     if (!CompressedOops::is_null(o)) {
449       oop obj = CompressedOops::decode_not_null(o);
450       if (_cset->is_in(obj)) {
451         oop fwd = ShenandoahForwarding::get_forwardee(obj);
452         if (EVAC && obj == fwd) {
453           fwd = _heap->evacuate_object(obj, _thread);
454         }
455         shenandoah_assert_forwarded_except(p, obj, _heap->cancelled_gc());
456         ShenandoahHeap::atomic_update_oop(fwd, p, o);
457         obj = fwd;
458       }
459     }
460   }
461 
462 public:
463   ShenandoahUpdateEvacForCloneOopClosure() :
464           _heap(ShenandoahHeap::heap()),
465           _cset(_heap->collection_set()),
466           _thread(Thread::current()) {}
467 
468   virtual void do_oop(oop* p)       { do_oop_work(p); }
469   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
470 };
471 
472 void ShenandoahBarrierSet::clone_evacuation(oop obj) {
473   assert(_heap->is_evacuation_in_progress(), "only during evacuation");
474   if (need_bulk_update(cast_from_oop<HeapWord*>(obj))) {
475     ShenandoahUpdateEvacForCloneOopClosure<true> cl;
476     obj->oop_iterate(&cl);
477   }
478 }
479 
480 void ShenandoahBarrierSet::clone_update(oop obj) {
481   assert(_heap->is_update_refs_in_progress(), "only during update-refs");
482   if (need_bulk_update(cast_from_oop<HeapWord*>(obj))) {
483     ShenandoahUpdateEvacForCloneOopClosure<false> cl;
484     obj->oop_iterate(&cl);
485   }
486 }
487 
488 template <DecoratorSet decorators, typename BarrierSetT>
489 void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
490   // Hot code path, called from compiler/runtime. Make sure fast path is fast.
491 
492   // Fix up src before doing the copy, if needed.
493   const char gc_state = ShenandoahThreadLocalData::gc_state(Thread::current());
494   if (gc_state != 0 && ShenandoahCloneBarrier) {
495     ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
496     if ((gc_state & ShenandoahHeap::EVACUATION) != 0) {
497       bs->clone_evacuation(src);
498     } else if ((gc_state & ShenandoahHeap::UPDATE_REFS) != 0) {
499       bs->clone_update(src);
500     }
501   }
502 
503   Raw::clone(src, dst, size);
504 
505   // Current allocator never allocates in old, so clone destination is guaranteed to be in young.
506   // Otherwise we need card barriers.
507   shenandoah_assert_in_young_if(nullptr, dst, ShenandoahCardBarrier);
508 }
509 
510 template <DecoratorSet decorators, typename BarrierSetT>
511 template <typename T>
512 OopCopyResult ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
513                                                                                                   arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
514                                                                                                   size_t length) {
515   T* src = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw);
516   T* dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw);
517 
518   ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
519   bs->arraycopy_barrier(src, dst, length);
520   OopCopyResult result = Raw::oop_arraycopy_in_heap(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
521   if (ShenandoahCardBarrier) {
522     bs->write_ref_array((HeapWord*) dst, length);
523   }
524   return result;
525 }
526 
527 template <class T, bool HAS_FWD, bool EVAC, bool ENQUEUE>
< prev index next >