mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8235324: Dying objects are published from users of CollectedHeap::object_iterate
Reviewed-by: pliden, eosterlund, sjohanss, rkennke
This commit is contained in:
parent
dc0cc5520c
commit
5b155f05e7
14 changed files with 53 additions and 8 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue