< 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 >