596
597 void ShenandoahConcurrentNMethodIterator::nmethods_do_begin() {
598 assert(CodeCache_lock->owned_by_self(), "Lock must be held");
599 assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
600 "Only for concurrent class unloading");
601 _table_snapshot = _table->snapshot_for_iteration();
602 }
603
604 void ShenandoahConcurrentNMethodIterator::nmethods_do(NMethodClosure* cl) {
605 assert(_table_snapshot != NULL, "Must first call nmethod_do_begin()");
606 _table_snapshot->concurrent_nmethods_do(cl);
607 }
608
609 void ShenandoahConcurrentNMethodIterator::nmethods_do_end() {
610 assert(CodeCache_lock->owned_by_self(), "Lock must be held");
611 assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
612 "Only for concurrent class unloading");
613 _table->finish_iteration(_table_snapshot);
614 CodeCache_lock->notify_all();
615 }
|
596
597 void ShenandoahConcurrentNMethodIterator::nmethods_do_begin() {
598 assert(CodeCache_lock->owned_by_self(), "Lock must be held");
599 assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
600 "Only for concurrent class unloading");
601 _table_snapshot = _table->snapshot_for_iteration();
602 }
603
604 void ShenandoahConcurrentNMethodIterator::nmethods_do(NMethodClosure* cl) {
605 assert(_table_snapshot != NULL, "Must first call nmethod_do_begin()");
606 _table_snapshot->concurrent_nmethods_do(cl);
607 }
608
609 void ShenandoahConcurrentNMethodIterator::nmethods_do_end() {
610 assert(CodeCache_lock->owned_by_self(), "Lock must be held");
611 assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
612 "Only for concurrent class unloading");
613 _table->finish_iteration(_table_snapshot);
614 CodeCache_lock->notify_all();
615 }
616
617 ShenandoahAbortableNMethodLocker::ShenandoahAbortableNMethodLocker(ShenandoahReentrantLock* lock) :
618 _heap(ShenandoahHeap::heap()), _lock(lock), _aborted(false) {
619 while (!_aborted) {
620 // Try lock first. Because we really don't want to abort,
621 // which may result massive deopt. from nmethod entry barrier
622 if (_lock->try_lock()) {
623 break;
624 } else if (_heap->cancelled_gc()) {
625 _aborted = true;
626 } else {
627 // Spin a little. Since the lock is per-nmethod, we can expect the other
628 // thread to release the lock fair soon.
629 for (int i = 0; i < 4096; i ++) {
630 SpinPause();
631 }
632 }
633 }
634 }
635
636 ShenandoahAbortableNMethodLocker::~ShenandoahAbortableNMethodLocker() {
637 if (_lock != NULL && !_aborted) {
638 assert(_lock->owned_by_self(), "Must be owner");
639 _lock->unlock();
640 }
641 }
|