--- a/src/hotspot/share/gc/z/zHeap.cpp Tue Nov 12 20:01:23 2019 +0000
+++ b/src/hotspot/share/gc/z/zHeap.cpp Tue Nov 12 20:14:49 2019 +0000
@@ -40,6 +40,7 @@
#include "logging/log.hpp"
#include "memory/iterator.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/handshake.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.hpp"
#include "utilities/debug.hpp"
@@ -315,7 +316,7 @@
// Process weak roots
_weak_roots_processor.process_weak_roots();
- // Prepare to unload unused classes and code
+ // Prepare to unload stale metadata and nmethods
_unload.prepare();
return true;
@@ -325,6 +326,11 @@
_reference_processor.set_soft_reference_policy(clear);
}
+class ZRendezvousClosure : public ThreadClosure {
+public:
+ virtual void do_thread(Thread* thread) {}
+};
+
void ZHeap::process_non_strong_references() {
// Process Soft/Weak/Final/PhantomReferences
_reference_processor.process_references();
@@ -332,8 +338,22 @@
// Process concurrent weak roots
_weak_roots_processor.process_concurrent_weak_roots();
- // Unload unused classes and code
- _unload.unload();
+ // Unlink stale metadata and nmethods
+ _unload.unlink();
+
+ // Perform a handshake. This is needed 1) to make sure that stale
+ // metadata and nmethods are no longer observable. And 2), to
+ // prevent the race where a mutator first loads an oop, which is
+ // logically null but not yet cleared. Then this oop gets cleared
+ // by the reference processor and resurrection is unblocked. At
+ // this point the mutator could see the unblocked state and pass
+ // this invalid oop through the normal barrier path, which would
+ // incorrectly try to mark the oop.
+ ZRendezvousClosure cl;
+ Handshake::execute(&cl);
+
+ // Purge stale metadata and nmethods that were unlinked
+ _unload.purge();
// Unblock resurrection of weak/phantom references
ZResurrection::unblock();
@@ -405,7 +425,7 @@
void ZHeap::relocate_start() {
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
- // Finish unloading of classes and code
+ // Finish unloading stale metadata and nmethods
_unload.finish();
// Flip address view