< prev index next >
src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
Print this page
rev 59811 : 8247670: Shenandoah: deadlock during class unloading OOME
*** 218,227 ****
--- 218,228 ----
class ShenandoahNMethodUnlinkClosure : public NMethodClosure {
private:
bool _unloading_occurred;
volatile bool _failed;
+ bool _refill_icBuffer;
ShenandoahHeap* const _heap;
BarrierSetNMethod* const _bs;
void set_failed() {
Atomic::store(&_failed, true);
*** 245,254 ****
--- 246,256 ----
}
public:
ShenandoahNMethodUnlinkClosure(bool unloading_occurred) :
_unloading_occurred(unloading_occurred),
_failed(false),
+ _refill_icBuffer(false),
_heap(ShenandoahHeap::heap()),
_bs(ShenandoahBarrierSet::barrier_set()->barrier_set_nmethod()) {}
virtual void do_nmethod(nmethod* nm) {
assert(_heap->is_concurrent_weak_root_in_progress(), "Only this phase");
*** 262,290 ****
if (!nm->is_alive()) {
return;
}
if (nm->is_unloading()) {
! ShenandoahReentrantLocker locker(nm_data->lock());
unlink(nm);
return;
}
! ShenandoahReentrantLocker locker(nm_data->lock());
// Heal oops and disarm
if (_bs->is_armed(nm)) {
ShenandoahNMethod::heal_nmethod_metadata(nm_data);
_bs->disarm(nm);
}
// Clear compiled ICs and exception caches
if (!nm->unload_nmethod_caches(_unloading_occurred)) {
set_failed();
}
}
bool failed() const {
return Atomic::load(&_failed);
}
};
--- 264,305 ----
if (!nm->is_alive()) {
return;
}
if (nm->is_unloading()) {
! ShenandoahAbortableNMethodLocker locker(nm_data->lock());
! if (locker.aborted()) {
! set_failed();
! } else {
unlink(nm);
+ }
return;
}
! ShenandoahAbortableNMethodLocker locker(nm_data->lock());
! if (locker.aborted()) {
! set_failed();
! return;
! }
// Heal oops and disarm
if (_bs->is_armed(nm)) {
ShenandoahNMethod::heal_nmethod_metadata(nm_data);
_bs->disarm(nm);
}
// Clear compiled ICs and exception caches
if (!nm->unload_nmethod_caches(_unloading_occurred)) {
+ _refill_icBuffer = true;
set_failed();
}
}
+ bool need_refill_icBuffer() const {
+ return _refill_icBuffer;
+ }
+
bool failed() const {
return Atomic::load(&_failed);
}
};
*** 316,348 ****
--- 331,371 ----
}
bool success() const {
return !_cl.failed();
}
+
+ bool need_refill_icBuffer() const {
+ return _cl.need_refill_icBuffer();
+ }
};
void ShenandoahCodeRoots::unlink(WorkGang* workers, bool unloading_occurred) {
assert(ShenandoahConcurrentRoots::should_do_concurrent_class_unloading(),
"Only when running concurrent class unloading");
for (;;) {
ICRefillVerifier verifier;
+ bool need_refill_icBuffer = false;
{
ShenandoahUnlinkTask task(unloading_occurred, &verifier);
workers->run_task(&task);
if (task.success()) {
return;
}
+ need_refill_icBuffer = task.need_refill_icBuffer();
}
+ if (need_refill_icBuffer) {
// Cleaning failed because we ran out of transitional IC stubs,
// so we have to refill and try again. Refilling requires taking
// a safepoint, so we temporarily leave the suspendible thread set.
SuspendibleThreadSetLeaver sts;
InlineCacheBuffer::refill_ic_stubs();
}
+ }
}
class ShenandoahNMethodPurgeClosure : public NMethodClosure {
public:
virtual void do_nmethod(nmethod* nm) {
< prev index next >