Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8254980: ZGC: ZHeapIterator visits armed nmethods with -XX:-ClassUnloading #801

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/hotspot/share/gc/z/zHeapIterator.cpp
Expand Up @@ -126,6 +126,17 @@ class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure {
CodeBlobToOopClosure code_cl(this, false /* fix_oop_relocations */);
thread->oops_do(this, &code_cl);
}

virtual ZNMethodEntry nmethod_entry() const {
if (ClassUnloading) {
// All encountered nmethods should have been "entered" during stack walking
return ZNMethodEntry::VerifyDisarmed;
} else {
// All nmethods are considered roots and will be visited.
// Make sure that the unvisited gets fixed and disarmed before proceeding.
return ZNMethodEntry::PreBarrier;
}
}
};

template <bool VisitReferents>
Expand Down
5 changes: 3 additions & 2 deletions src/hotspot/share/gc/z/zMark.cpp
Expand Up @@ -582,8 +582,9 @@ class ZMarkConcurrentRootsIteratorClosure : public ZRootsIteratorClosure {
ZThreadLocalAllocBuffer::publish_statistics();
}

virtual bool should_disarm_nmethods() const {
return true;
virtual ZNMethodEntry nmethod_entry() const {
// Only apply closure to armed nmethods, and then disarm them.
return ZNMethodEntry::Disarm;
}

virtual void do_thread(Thread* thread) {
Expand Down
32 changes: 23 additions & 9 deletions src/hotspot/share/gc/z/zNMethod.cpp
Expand Up @@ -236,28 +236,42 @@ void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) {

class ZNMethodToOopsDoClosure : public NMethodClosure {
private:
OopClosure* const _cl;
const bool _should_disarm_nmethods;
OopClosure* const _cl;
const ZNMethodEntry _entry;
BarrierSetNMethod* const _bs_nm;

public:
ZNMethodToOopsDoClosure(OopClosure* cl, bool should_disarm_nmethods) :
ZNMethodToOopsDoClosure(OopClosure* cl, ZNMethodEntry entry) :
_cl(cl),
_should_disarm_nmethods(should_disarm_nmethods) {}
_entry(entry),
_bs_nm(BarrierSet::barrier_set()->barrier_set_nmethod()) {}

virtual void do_nmethod(nmethod* nm) {
if (_entry == ZNMethodEntry::PreBarrier) {
// Apply entry barrier before proceeding with closure
_bs_nm->nmethod_entry_barrier(nm);
}

ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
if (!nm->is_alive()) {
return;
}

if (_should_disarm_nmethods) {
if (_entry == ZNMethodEntry::Disarm) {
// Apply closure and disarm only armed nmethods
if (ZNMethod::is_armed(nm)) {
ZNMethod::nmethod_oops_do(nm, _cl);
ZNMethod::disarm(nm);
}
} else {
ZNMethod::nmethod_oops_do(nm, _cl);
return;
}

if (_entry == ZNMethodEntry::VerifyDisarmed) {
// Only verify
assert(!ZNMethod::is_armed(nm), "Must be disarmed");
}

ZNMethod::nmethod_oops_do(nm, _cl);
}
};

Expand All @@ -269,8 +283,8 @@ void ZNMethod::oops_do_end() {
ZNMethodTable::nmethods_do_end();
}

void ZNMethod::oops_do(OopClosure* cl, bool should_disarm_nmethods) {
ZNMethodToOopsDoClosure nmethod_cl(cl, should_disarm_nmethods);
void ZNMethod::oops_do(OopClosure* cl, ZNMethodEntry entry) {
ZNMethodToOopsDoClosure nmethod_cl(cl, entry);
ZNMethodTable::nmethods_do(&nmethod_cl);
}

Expand Down
9 changes: 8 additions & 1 deletion src/hotspot/share/gc/z/zNMethod.hpp
Expand Up @@ -31,6 +31,13 @@ class OopClosure;
class ZReentrantLock;
class ZWorkers;

enum class ZNMethodEntry {
PreBarrier,
Disarm,
VerifyDisarmed,
None
};

class ZNMethod : public AllStatic {
private:
static void attach_gc_data(nmethod* nm);
Expand All @@ -52,7 +59,7 @@ class ZNMethod : public AllStatic {

static void oops_do_begin();
static void oops_do_end();
static void oops_do(OopClosure* cl, bool should_disarm_nmethods);
static void oops_do(OopClosure* cl, ZNMethodEntry entry);

static ZReentrantLock* lock_for_nmethod(nmethod* nm);

Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/gc/z/zOopClosures.hpp
Expand Up @@ -57,12 +57,16 @@ class ZPhantomKeepAliveOopClosure : public ZRootsIteratorClosure {
public:
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);

virtual ZNMethodEntry nmethod_entry() const;
};

class ZPhantomCleanOopClosure : public ZRootsIteratorClosure {
public:
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);

virtual ZNMethodEntry nmethod_entry() const;
};

#endif // SHARE_GC_Z_ZOOPCLOSURES_HPP
10 changes: 10 additions & 0 deletions src/hotspot/share/gc/z/zOopClosures.inline.hpp
Expand Up @@ -80,6 +80,11 @@ inline void ZPhantomKeepAliveOopClosure::do_oop(oop* p) {
ZBarrier::keep_alive_barrier_on_phantom_oop_field(p);
}

inline ZNMethodEntry ZPhantomKeepAliveOopClosure::nmethod_entry() const {
ShouldNotReachHere();
return ZNMethodEntry::None;
}

inline void ZPhantomKeepAliveOopClosure::do_oop(narrowOop* p) {
ShouldNotReachHere();
}
Expand All @@ -104,4 +109,9 @@ inline void ZPhantomCleanOopClosure::do_oop(narrowOop* p) {
ShouldNotReachHere();
}

inline ZNMethodEntry ZPhantomCleanOopClosure::nmethod_entry() const {
ShouldNotReachHere();
return ZNMethodEntry::None;
}

#endif // SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/z/zRootsIterator.cpp
Expand Up @@ -122,7 +122,7 @@ void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure*

void ZConcurrentRootsIterator::do_code_cache(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhaseConcurrentRootsCodeCache);
ZNMethod::oops_do(cl, cl->should_disarm_nmethods());
ZNMethod::oops_do(cl, cl->nmethod_entry());
}

class ZConcurrentRootsIteratorThreadClosure : public ThreadClosure {
Expand Down
5 changes: 2 additions & 3 deletions src/hotspot/share/gc/z/zRootsIterator.hpp
Expand Up @@ -26,6 +26,7 @@

#include "classfile/classLoaderDataGraph.hpp"
#include "gc/shared/oopStorageSetParState.hpp"
#include "gc/z/zNMethod.hpp"
#include "memory/allocation.hpp"
#include "memory/iterator.hpp"
#include "runtime/threadSMR.hpp"
Expand Down Expand Up @@ -61,9 +62,7 @@ class ZRootsIteratorClosure : public OopClosure {
public:
virtual void do_thread(Thread* thread) {}

virtual bool should_disarm_nmethods() const {
return false;
}
virtual ZNMethodEntry nmethod_entry() const = 0;
};

class ZJavaThreadsIterator {
Expand Down
7 changes: 6 additions & 1 deletion src/hotspot/share/gc/z/zVerify.cpp
Expand Up @@ -94,6 +94,11 @@ class ZVerifyRootClosure : public ZRootsIteratorClosure {
bool verify_fixed() const {
return _verify_fixed;
}

virtual ZNMethodEntry nmethod_entry() const {
// Verification performs its own verification
return ZNMethodEntry::None;
}
};

class ZVerifyCodeBlobClosure : public CodeBlobToOopClosure {
Expand Down Expand Up @@ -188,7 +193,7 @@ void ZVerifyRootClosure::do_thread(Thread* thread) {
verify_stack.verify_frames();
}

class ZVerifyOopClosure : public ClaimMetadataVisitingOopIterateClosure, public ZRootsIteratorClosure {
class ZVerifyOopClosure : public ClaimMetadataVisitingOopIterateClosure {
private:
const bool _verify_weaks;

Expand Down