8235324: Dying objects are published from users of CollectedHeap::object_iterate

Reviewed-by: pliden, eosterlund, sjohanss, rkennke
This commit is contained in:
Stefan Karlsson 2019-12-04 11:30:32 +01:00
parent dc0cc5520c
commit 5b155f05e7
14 changed files with 53 additions and 8 deletions

View file

@ -2348,6 +2348,10 @@ void G1CollectedHeap::object_iterate(ObjectClosure* cl) {
heap_region_iterate(&blk); heap_region_iterate(&blk);
} }
void G1CollectedHeap::keep_alive(oop obj) {
G1BarrierSet::enqueue(obj);
}
void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const {
_hrm->iterate(cl); _hrm->iterate(cl);
} }

View file

@ -1170,6 +1170,9 @@ public:
// Iterate over all objects, calling "cl.do_object" on each. // Iterate over all objects, calling "cl.do_object" on each.
virtual void object_iterate(ObjectClosure* cl); virtual void object_iterate(ObjectClosure* cl);
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
virtual void keep_alive(oop obj);
// Iterate over heap regions, in address order, terminating the // Iterate over heap regions, in address order, terminating the
// iteration early if the "do_heap_region" method returns "true". // iteration early if the "do_heap_region" method returns "true".
void heap_region_iterate(HeapRegionClosure* blk) const; void heap_region_iterate(HeapRegionClosure* blk) const;

View file

@ -387,6 +387,9 @@ class CollectedHeap : public CHeapObj<mtInternal> {
// Iterate over all objects, calling "cl.do_object" on each. // Iterate over all objects, calling "cl.do_object" on each.
virtual void object_iterate(ObjectClosure* cl) = 0; virtual void object_iterate(ObjectClosure* cl) = 0;
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
virtual void keep_alive(oop obj) {}
// Returns the longest time (in ms) that has elapsed since the last // Returns the longest time (in ms) that has elapsed since the last
// time that any part of the heap was examined by a garbage collection. // time that any part of the heap was examined by a garbage collection.
virtual jlong millis_since_last_gc() = 0; virtual jlong millis_since_last_gc() = 0;

View file

@ -1327,6 +1327,11 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) {
} }
} }
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
void ShenandoahHeap::keep_alive(oop obj) {
ShenandoahBarrierSet::barrier_set()->enqueue(obj);
}
void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const { void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const {
for (size_t i = 0; i < num_regions(); i++) { for (size_t i = 0; i < num_regions(); i++) {
ShenandoahHeapRegion* current = get_region(i); ShenandoahHeapRegion* current = get_region(i);

View file

@ -560,6 +560,9 @@ public:
// Used for native heap walkers: heap dumpers, mostly // Used for native heap walkers: heap dumpers, mostly
void object_iterate(ObjectClosure* cl); void object_iterate(ObjectClosure* cl);
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
void keep_alive(oop obj);
// Used by RMI // Used by RMI
jlong millis_since_last_gc(); jlong millis_since_last_gc();

View file

@ -31,14 +31,6 @@
#include "runtime/safepoint.hpp" #include "runtime/safepoint.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
bool ZBarrier::during_mark() {
return ZGlobalPhase == ZPhaseMark;
}
bool ZBarrier::during_relocate() {
return ZGlobalPhase == ZPhaseRelocate;
}
template <bool finalizable> template <bool finalizable>
bool ZBarrier::should_mark_through(uintptr_t addr) { bool ZBarrier::should_mark_through(uintptr_t addr) {
// Finalizable marked oops can still exists on the heap after marking // Finalizable marked oops can still exists on the heap after marking

View file

@ -105,6 +105,7 @@ public:
static void keep_alive_barrier_on_weak_oop_field(volatile oop* p); static void keep_alive_barrier_on_weak_oop_field(volatile oop* p);
static void keep_alive_barrier_on_phantom_oop_field(volatile oop* p); static void keep_alive_barrier_on_phantom_oop_field(volatile oop* p);
static void keep_alive_barrier_on_phantom_root_oop_field(oop* p); static void keep_alive_barrier_on_phantom_root_oop_field(oop* p);
static void keep_alive_barrier_on_oop(oop o);
// Mark barrier // Mark barrier
static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable); static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable);

View file

@ -144,6 +144,14 @@ inline bool ZBarrier::is_weak_good_or_null_fast_path(uintptr_t addr) {
return ZAddress::is_weak_good_or_null(addr); return ZAddress::is_weak_good_or_null(addr);
} }
inline bool ZBarrier::during_mark() {
return ZGlobalPhase == ZPhaseMark;
}
inline bool ZBarrier::during_relocate() {
return ZGlobalPhase == ZPhaseRelocate;
}
// //
// Load barrier // Load barrier
// //
@ -291,6 +299,12 @@ inline void ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(oop* p) {
root_barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o); root_barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o);
} }
inline void ZBarrier::keep_alive_barrier_on_oop(oop o) {
if (during_mark()) {
barrier<is_null_fast_path, mark_barrier_on_oop_slow_path>(NULL, o);
}
}
// //
// Mark barrier // Mark barrier
// //

View file

@ -247,6 +247,10 @@ void ZCollectedHeap::object_iterate(ObjectClosure* cl) {
_heap.object_iterate(cl, true /* visit_weaks */); _heap.object_iterate(cl, true /* visit_weaks */);
} }
void ZCollectedHeap::keep_alive(oop obj) {
_heap.keep_alive(obj);
}
void ZCollectedHeap::register_nmethod(nmethod* nm) { void ZCollectedHeap::register_nmethod(nmethod* nm) {
ZNMethod::register_nmethod(nm); ZNMethod::register_nmethod(nm);
} }

View file

@ -99,6 +99,8 @@ public:
virtual void object_iterate(ObjectClosure* cl); virtual void object_iterate(ObjectClosure* cl);
virtual void keep_alive(oop obj);
virtual void register_nmethod(nmethod* nm); virtual void register_nmethod(nmethod* nm);
virtual void unregister_nmethod(nmethod* nm); virtual void unregister_nmethod(nmethod* nm);
virtual void flush_nmethod(nmethod* nm); virtual void flush_nmethod(nmethod* nm);

View file

@ -322,6 +322,10 @@ bool ZHeap::mark_end() {
return true; return true;
} }
void ZHeap::keep_alive(oop obj) {
ZBarrier::keep_alive_barrier_on_oop(obj);
}
void ZHeap::set_soft_reference_policy(bool clear) { void ZHeap::set_soft_reference_policy(bool clear) {
_reference_processor.set_soft_reference_policy(clear); _reference_processor.set_soft_reference_policy(clear);
} }

View file

@ -137,6 +137,7 @@ public:
void mark(bool initial); void mark(bool initial);
void mark_flush_and_free(Thread* thread); void mark_flush_and_free(Thread* thread);
bool mark_end(); bool mark_end();
void keep_alive(oop obj);
// Relocation set // Relocation set
void select_relocation_set(); void select_relocation_set();

View file

@ -778,6 +778,10 @@ class FindInstanceClosure : public ObjectClosure {
void do_object(oop obj) { void do_object(oop obj) {
if (obj->is_a(_klass)) { if (obj->is_a(_klass)) {
// obj was read with AS_NO_KEEPALIVE, or equivalent.
// The object needs to be kept alive when it is published.
Universe::heap()->keep_alive(obj);
_result->append(obj); _result->append(obj);
} }
} }

View file

@ -483,6 +483,11 @@ JvmtiTagMap::~JvmtiTagMap() {
// is returned. Otherwise an new entry is allocated. // is returned. Otherwise an new entry is allocated.
JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) { JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) {
assert(Thread::current()->is_VM_thread() || is_locked(), "checking"); assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
// ref was read with AS_NO_KEEPALIVE, or equivalent.
// The object needs to be kept alive when it is published.
Universe::heap()->keep_alive(ref);
JvmtiTagHashmapEntry* entry; JvmtiTagHashmapEntry* entry;
if (_free_entries == NULL) { if (_free_entries == NULL) {
entry = new JvmtiTagHashmapEntry(ref, tag); entry = new JvmtiTagHashmapEntry(ref, tag);