8276696: ParallelObjectIterator freed at the wrong time in VM_HeapDumper
Reviewed-by: pliden, stefank
This commit is contained in:
parent
90f96fb4db
commit
f4dc03ea6d
@ -2260,7 +2260,7 @@ void G1CollectedHeap::object_iterate(ObjectClosure* cl) {
|
||||
heap_region_iterate(&blk);
|
||||
}
|
||||
|
||||
class G1ParallelObjectIterator : public ParallelObjectIterator {
|
||||
class G1ParallelObjectIterator : public ParallelObjectIteratorImpl {
|
||||
private:
|
||||
G1CollectedHeap* _heap;
|
||||
HeapRegionClaimer _claimer;
|
||||
@ -2275,7 +2275,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
ParallelObjectIterator* G1CollectedHeap::parallel_object_iterator(uint thread_num) {
|
||||
ParallelObjectIteratorImpl* G1CollectedHeap::parallel_object_iterator(uint thread_num) {
|
||||
return new G1ParallelObjectIterator(thread_num);
|
||||
}
|
||||
|
||||
|
@ -1077,7 +1077,7 @@ public:
|
||||
// Iterate over all objects, calling "cl.do_object" on each.
|
||||
void object_iterate(ObjectClosure* cl) override;
|
||||
|
||||
ParallelObjectIterator* parallel_object_iterator(uint thread_num) override;
|
||||
ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num) override;
|
||||
|
||||
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
||||
void keep_alive(oop obj) override;
|
||||
|
@ -600,7 +600,7 @@ void ParallelScavengeHeap::object_iterate_parallel(ObjectClosure* cl,
|
||||
}
|
||||
}
|
||||
|
||||
class PSScavengeParallelObjectIterator : public ParallelObjectIterator {
|
||||
class PSScavengeParallelObjectIterator : public ParallelObjectIteratorImpl {
|
||||
private:
|
||||
ParallelScavengeHeap* _heap;
|
||||
HeapBlockClaimer _claimer;
|
||||
@ -615,7 +615,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
ParallelObjectIterator* ParallelScavengeHeap::parallel_object_iterator(uint thread_num) {
|
||||
ParallelObjectIteratorImpl* ParallelScavengeHeap::parallel_object_iterator(uint thread_num) {
|
||||
return new PSScavengeParallelObjectIterator();
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ class ParallelScavengeHeap : public CollectedHeap {
|
||||
|
||||
void object_iterate(ObjectClosure* cl);
|
||||
void object_iterate_parallel(ObjectClosure* cl, HeapBlockClaimer* claimer);
|
||||
virtual ParallelObjectIterator* parallel_object_iterator(uint thread_num);
|
||||
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num);
|
||||
|
||||
HeapWord* block_start(const void* addr) const;
|
||||
bool block_is_obj(const HeapWord* addr) const;
|
||||
|
@ -110,6 +110,18 @@ void GCHeapLog::log_heap(CollectedHeap* heap, bool before) {
|
||||
st.print_cr("}");
|
||||
}
|
||||
|
||||
ParallelObjectIterator::ParallelObjectIterator(uint thread_num) :
|
||||
_impl(Universe::heap()->parallel_object_iterator(thread_num))
|
||||
{}
|
||||
|
||||
ParallelObjectIterator::~ParallelObjectIterator() {
|
||||
delete _impl;
|
||||
}
|
||||
|
||||
void ParallelObjectIterator::object_iterate(ObjectClosure* cl, uint worker_id) {
|
||||
_impl->object_iterate(cl, worker_id);
|
||||
}
|
||||
|
||||
size_t CollectedHeap::unused() const {
|
||||
MutexLocker ml(Heap_lock);
|
||||
return capacity() - used();
|
||||
|
@ -62,10 +62,23 @@ class VirtualSpaceSummary;
|
||||
class WorkerThreads;
|
||||
class nmethod;
|
||||
|
||||
class ParallelObjectIterator : public CHeapObj<mtGC> {
|
||||
class ParallelObjectIteratorImpl : public CHeapObj<mtGC> {
|
||||
public:
|
||||
virtual ~ParallelObjectIteratorImpl() {}
|
||||
virtual void object_iterate(ObjectClosure* cl, uint worker_id) = 0;
|
||||
virtual ~ParallelObjectIterator() {}
|
||||
};
|
||||
|
||||
// User facing parallel object iterator. This is a StackObj, which ensures that
|
||||
// the _impl is allocated and deleted in the scope of this object. This ensures
|
||||
// the life cycle of the implementation is as required by ThreadsListHandle,
|
||||
// which is sometimes used by the root iterators.
|
||||
class ParallelObjectIterator : public StackObj {
|
||||
ParallelObjectIteratorImpl* _impl;
|
||||
|
||||
public:
|
||||
ParallelObjectIterator(uint thread_num);
|
||||
~ParallelObjectIterator();
|
||||
void object_iterate(ObjectClosure* cl, uint worker_id);
|
||||
};
|
||||
|
||||
//
|
||||
@ -82,6 +95,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||||
friend class JVMCIVMStructs;
|
||||
friend class IsGCActiveMark; // Block structured external access to _is_gc_active
|
||||
friend class MemAllocator;
|
||||
friend class ParallelObjectIterator;
|
||||
|
||||
private:
|
||||
GCHeapLog* _gc_heap_log;
|
||||
@ -384,10 +398,12 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||||
// Iterate over all objects, calling "cl.do_object" on each.
|
||||
virtual void object_iterate(ObjectClosure* cl) = 0;
|
||||
|
||||
virtual ParallelObjectIterator* parallel_object_iterator(uint thread_num) {
|
||||
protected:
|
||||
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
||||
virtual void keep_alive(oop obj) {}
|
||||
|
||||
|
@ -1366,7 +1366,7 @@ public:
|
||||
// parallel marking queues.
|
||||
// Every worker processes it's own marking queue. work-stealing is used
|
||||
// to balance workload.
|
||||
class ShenandoahParallelObjectIterator : public ParallelObjectIterator {
|
||||
class ShenandoahParallelObjectIterator : public ParallelObjectIteratorImpl {
|
||||
private:
|
||||
uint _num_workers;
|
||||
bool _init_ready;
|
||||
@ -1465,7 +1465,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
ParallelObjectIterator* ShenandoahHeap::parallel_object_iterator(uint workers) {
|
||||
ParallelObjectIteratorImpl* ShenandoahHeap::parallel_object_iterator(uint workers) {
|
||||
return new ShenandoahParallelObjectIterator(workers, &_aux_bit_map);
|
||||
}
|
||||
|
||||
|
@ -484,7 +484,7 @@ public:
|
||||
// Used for native heap walkers: heap dumpers, mostly
|
||||
void object_iterate(ObjectClosure* cl);
|
||||
// Parallel heap iteration support
|
||||
virtual ParallelObjectIterator* parallel_object_iterator(uint workers);
|
||||
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint workers);
|
||||
|
||||
// Keep alive an object that was loaded with AS_NO_KEEPALIVE.
|
||||
void keep_alive(oop obj);
|
||||
|
@ -226,7 +226,7 @@ void ZCollectedHeap::object_iterate(ObjectClosure* cl) {
|
||||
_heap.object_iterate(cl, true /* visit_weaks */);
|
||||
}
|
||||
|
||||
ParallelObjectIterator* ZCollectedHeap::parallel_object_iterator(uint nworkers) {
|
||||
ParallelObjectIteratorImpl* ZCollectedHeap::parallel_object_iterator(uint nworkers) {
|
||||
return _heap.parallel_object_iterator(nworkers, true /* visit_weaks */);
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ public:
|
||||
virtual GrowableArray<MemoryPool*> memory_pools();
|
||||
|
||||
virtual void object_iterate(ObjectClosure* cl);
|
||||
virtual ParallelObjectIterator* parallel_object_iterator(uint nworkers);
|
||||
virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint nworkers);
|
||||
|
||||
virtual void keep_alive(oop obj);
|
||||
|
||||
|
@ -439,7 +439,7 @@ void ZHeap::object_iterate(ObjectClosure* cl, bool visit_weaks) {
|
||||
iter.object_iterate(cl, 0 /* worker_id */);
|
||||
}
|
||||
|
||||
ParallelObjectIterator* ZHeap::parallel_object_iterator(uint nworkers, bool visit_weaks) {
|
||||
ParallelObjectIteratorImpl* ZHeap::parallel_object_iterator(uint nworkers, bool visit_weaks) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
|
||||
return new ZHeapIterator(nworkers, visit_weaks);
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public:
|
||||
|
||||
// Iteration
|
||||
void object_iterate(ObjectClosure* cl, bool visit_weaks);
|
||||
ParallelObjectIterator* parallel_object_iterator(uint nworkers, bool visit_weaks);
|
||||
ParallelObjectIteratorImpl* parallel_object_iterator(uint nworkers, bool visit_weaks);
|
||||
void pages_do(ZPageClosure* cl);
|
||||
|
||||
// Serviceability
|
||||
|
@ -42,7 +42,7 @@ using ZHeapIteratorQueues = GenericTaskQueueSet<ZHeapIteratorQueue, mtGC>;
|
||||
using ZHeapIteratorArrayQueue = OverflowTaskQueue<ObjArrayTask, mtGC>;
|
||||
using ZHeapIteratorArrayQueues = GenericTaskQueueSet<ZHeapIteratorArrayQueue, mtGC>;
|
||||
|
||||
class ZHeapIterator : public ParallelObjectIterator {
|
||||
class ZHeapIterator : public ParallelObjectIteratorImpl {
|
||||
friend class ZHeapIteratorContext;
|
||||
|
||||
private:
|
||||
|
@ -578,18 +578,12 @@ uintx HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *fil
|
||||
const uint capped_parallel_thread_num = MIN2(parallel_thread_num, workers->max_workers());
|
||||
WithActiveWorkers with_active_workers(workers, capped_parallel_thread_num);
|
||||
|
||||
ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(workers->active_workers());
|
||||
if (poi != NULL) {
|
||||
// The GC supports parallel object iteration.
|
||||
|
||||
ParHeapInspectTask task(poi, cit, filter);
|
||||
// Run task with the active workers.
|
||||
workers->run_task(&task);
|
||||
|
||||
delete poi;
|
||||
if (task.success()) {
|
||||
return task.missed_count();
|
||||
}
|
||||
ParallelObjectIterator poi(workers->active_workers());
|
||||
ParHeapInspectTask task(&poi, cit, filter);
|
||||
// Run task with the active workers.
|
||||
workers->run_task(&task);
|
||||
if (task.success()) {
|
||||
return task.missed_count();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1910,7 +1910,6 @@ class VM_HeapDumper : public VM_GC_Operation, public WorkerTask {
|
||||
// Number of dumper threads that only iterate heap.
|
||||
uint _heap_only_dumper_threads = _num_dumper_threads - 1 /* VMDumper thread */;
|
||||
_dumper_controller = new (std::nothrow) DumperController(_heap_only_dumper_threads);
|
||||
_poi = Universe::heap()->parallel_object_iterator(_num_dumper_threads);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1999,10 +1998,6 @@ class VM_HeapDumper : public VM_GC_Operation, public WorkerTask {
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(ThreadStackTrace*, _stack_traces);
|
||||
}
|
||||
if (_poi != NULL) {
|
||||
delete _poi;
|
||||
_poi = NULL;
|
||||
}
|
||||
if (_dumper_controller != NULL) {
|
||||
delete _dumper_controller;
|
||||
_dumper_controller = NULL;
|
||||
@ -2252,7 +2247,14 @@ void VM_HeapDumper::doit() {
|
||||
work(0);
|
||||
} else {
|
||||
prepare_parallel_dump(workers->active_workers());
|
||||
workers->run_task(this);
|
||||
if (_num_dumper_threads > 1) {
|
||||
ParallelObjectIterator poi(_num_dumper_threads);
|
||||
_poi = &poi;
|
||||
workers->run_task(this);
|
||||
_poi = NULL;
|
||||
} else {
|
||||
workers->run_task(this);
|
||||
}
|
||||
finish_parallel_dump();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user