From 8ed9da8566e3b77e50e640bd2310df60587501a0 Mon Sep 17 00:00:00 2001 From: jmasa Date: Tue, 6 Jan 2009 07:05:05 -0800 Subject: [PATCH] 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off Summary: Added safe_object_iterate() for use by JMapPerm. Reviewed-by: tonyp --- .../compactibleFreeListSpace.cpp | 24 +++++++++++++++++++ .../compactibleFreeListSpace.hpp | 9 +++++++ .../concurrentMarkSweepGeneration.cpp | 11 ++++++++- .../concurrentMarkSweepGeneration.hpp | 1 + .../gc_implementation/g1/g1CollectedHeap.hpp | 1 + .../parallelScavenge/parallelScavengeHeap.hpp | 1 + src/share/vm/gc_interface/collectedHeap.hpp | 4 ++++ src/share/vm/memory/genCollectedHeap.cpp | 7 ++++++ src/share/vm/memory/genCollectedHeap.hpp | 1 + src/share/vm/memory/generation.cpp | 15 ++++++++++++ src/share/vm/memory/generation.hpp | 5 ++++ src/share/vm/memory/heapInspection.cpp | 6 +++++ src/share/vm/memory/space.cpp | 6 +++++ src/share/vm/memory/space.hpp | 6 +++++ src/share/vm/prims/jvmtiTagMap.cpp | 3 +++ src/share/vm/services/heapDumper.cpp | 2 +- 16 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 4b1fecd7c..d8b81244c 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -706,6 +706,30 @@ void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) { } } +// Apply the given closure to each live object in the space +// The usage of CompactibleFreeListSpace +// by the ConcurrentMarkSweepGeneration for concurrent GC's allows +// objects in the space with references to objects that are no longer +// valid. For example, an object may reference another object +// that has already been sweep up (collected). This method uses +// obj_is_alive() to determine whether it is safe to apply the closure to +// an object. See obj_is_alive() for details on how liveness of an +// object is decided. + +void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { + assert_lock_strong(freelistLock()); + NOT_PRODUCT(verify_objects_initialized()); + HeapWord *cur, *limit; + size_t curSize; + for (cur = bottom(), limit = end(); cur < limit; + cur += curSize) { + curSize = block_size(cur); + if (block_is_obj(cur) && obj_is_alive(cur)) { + blk->do_object(oop(cur)); + } + } +} + void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) { assert_locked(); diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 5306a8f30..e0c48a1b7 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -481,6 +481,15 @@ class CompactibleFreeListSpace: public CompactibleSpace { void oop_iterate(OopClosure* cl); void object_iterate(ObjectClosure* blk); + // Apply the closure to each object in the space whose references + // point to objects in the heap. The usage of CompactibleFreeListSpace + // by the ConcurrentMarkSweepGeneration for concurrent GC's allows + // objects in the space with references to objects that are no longer + // valid. For example, an object may reference another object + // that has already been sweep up (collected). This method uses + // obj_is_alive() to determine whether it is safe to iterate of + // an object. + void safe_object_iterate(ObjectClosure* blk); void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); // Requires that "mr" be entirely within the space. diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index e83441076..83de6e6d4 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -3017,6 +3017,16 @@ ConcurrentMarkSweepGeneration::object_iterate(ObjectClosure* cl) { } } +void +ConcurrentMarkSweepGeneration::safe_object_iterate(ObjectClosure* cl) { + if (freelistLock()->owned_by_self()) { + Generation::safe_object_iterate(cl); + } else { + MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); + Generation::safe_object_iterate(cl); + } +} + void ConcurrentMarkSweepGeneration::pre_adjust_pointers() { } @@ -7001,7 +7011,6 @@ void MarkFromRootsClosure::scanOopsInOop(HeapWord* ptr) { _mut->clear_range(mr); } DEBUG_ONLY(}) - // Note: the finger doesn't advance while we drain // the stack below. PushOrMarkClosure pushOrMarkClosure(_collector, diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index 44ef14e8d..dacf5873a 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -1212,6 +1212,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { // More iteration support virtual void oop_iterate(MemRegion mr, OopClosure* cl); virtual void oop_iterate(OopClosure* cl); + virtual void safe_object_iterate(ObjectClosure* cl); virtual void object_iterate(ObjectClosure* cl); // Need to declare the full complement of closures, whether we'll diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 557456e40..63688de38 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -850,6 +850,7 @@ public: // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl); + virtual void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); } // Iterate over all objects allocated since the last collection, calling // "cl.do_object" on each. The heap must have been initialized properly diff --git a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp index 087cdf93c..c268b6a2f 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp @@ -200,6 +200,7 @@ class ParallelScavengeHeap : public CollectedHeap { void oop_iterate(OopClosure* cl); void object_iterate(ObjectClosure* cl); + void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); } void permanent_oop_iterate(OopClosure* cl); void permanent_object_iterate(ObjectClosure* cl); diff --git a/src/share/vm/gc_interface/collectedHeap.hpp b/src/share/vm/gc_interface/collectedHeap.hpp index 13d30c70b..41d80a3a9 100644 --- a/src/share/vm/gc_interface/collectedHeap.hpp +++ b/src/share/vm/gc_interface/collectedHeap.hpp @@ -466,6 +466,10 @@ class CollectedHeap : public CHeapObj { // This includes objects in permanent memory. virtual void object_iterate(ObjectClosure* cl) = 0; + // Similar to object_iterate() except iterates only + // over live objects. + virtual void safe_object_iterate(ObjectClosure* cl) = 0; + // Behaves the same as oop_iterate, except only traverses // interior pointers contained in permanent memory. If there // is no permanent memory, does nothing. diff --git a/src/share/vm/memory/genCollectedHeap.cpp b/src/share/vm/memory/genCollectedHeap.cpp index 832a3331e..41dfac1b5 100644 --- a/src/share/vm/memory/genCollectedHeap.cpp +++ b/src/share/vm/memory/genCollectedHeap.cpp @@ -910,6 +910,13 @@ void GenCollectedHeap::object_iterate(ObjectClosure* cl) { perm_gen()->object_iterate(cl); } +void GenCollectedHeap::safe_object_iterate(ObjectClosure* cl) { + for (int i = 0; i < _n_gens; i++) { + _gens[i]->safe_object_iterate(cl); + } + perm_gen()->safe_object_iterate(cl); +} + void GenCollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) { for (int i = 0; i < _n_gens; i++) { _gens[i]->object_iterate_since_last_GC(cl); diff --git a/src/share/vm/memory/genCollectedHeap.hpp b/src/share/vm/memory/genCollectedHeap.hpp index f9a4d5087..3ab20cfd1 100644 --- a/src/share/vm/memory/genCollectedHeap.hpp +++ b/src/share/vm/memory/genCollectedHeap.hpp @@ -215,6 +215,7 @@ public: void oop_iterate(OopClosure* cl); void oop_iterate(MemRegion mr, OopClosure* cl); void object_iterate(ObjectClosure* cl); + void safe_object_iterate(ObjectClosure* cl); void object_iterate_since_last_GC(ObjectClosure* cl); Space* space_containing(const void* addr) const; diff --git a/src/share/vm/memory/generation.cpp b/src/share/vm/memory/generation.cpp index 5167db243..d7b1d9f87 100644 --- a/src/share/vm/memory/generation.cpp +++ b/src/share/vm/memory/generation.cpp @@ -319,6 +319,21 @@ void Generation::object_iterate(ObjectClosure* cl) { space_iterate(&blk); } +class GenerationSafeObjIterateClosure : public SpaceClosure { + private: + ObjectClosure* _cl; + public: + virtual void do_space(Space* s) { + s->safe_object_iterate(_cl); + } + GenerationSafeObjIterateClosure(ObjectClosure* cl) : _cl(cl) {} +}; + +void Generation::safe_object_iterate(ObjectClosure* cl) { + GenerationSafeObjIterateClosure blk(cl); + space_iterate(&blk); +} + void Generation::prepare_for_compaction(CompactPoint* cp) { // Generic implementation, can be specialized CompactibleSpace* space = first_compaction_space(); diff --git a/src/share/vm/memory/generation.hpp b/src/share/vm/memory/generation.hpp index 0f0e74e47..206949901 100644 --- a/src/share/vm/memory/generation.hpp +++ b/src/share/vm/memory/generation.hpp @@ -518,6 +518,11 @@ class Generation: public CHeapObj { // each. virtual void object_iterate(ObjectClosure* cl); + // Iterate over all safe objects in the generation, calling "cl.do_object" on + // each. An object is safe if its references point to other objects in + // the heap. This defaults to object_iterate() unless overridden. + virtual void safe_object_iterate(ObjectClosure* cl); + // Iterate over all objects allocated in the generation since the last // collection, calling "cl.do_object" on each. The generation must have // been initialized properly to support this function, or else this call diff --git a/src/share/vm/memory/heapInspection.cpp b/src/share/vm/memory/heapInspection.cpp index e3d6fbd7b..3bc17bea6 100644 --- a/src/share/vm/memory/heapInspection.cpp +++ b/src/share/vm/memory/heapInspection.cpp @@ -263,6 +263,9 @@ void HeapInspection::heap_inspection(outputStream* st) { if (!cit.allocation_failed()) { // Iterate over objects in the heap RecordInstanceClosure ric(&cit); + // If this operation encounters a bad object when using CMS, + // consider using safe_object_iterate() which avoids perm gen + // objects that may contain bad references. Universe::heap()->object_iterate(&ric); // Report if certain classes are not counted because of @@ -317,5 +320,8 @@ void HeapInspection::find_instances_at_safepoint(klassOop k, GrowableArray* // Iterate over objects in the heap FindInstanceClosure fic(k, result); + // If this operation encounters a bad object when using CMS, + // consider using safe_object_iterate() which avoids perm gen + // objects that may contain bad references. Universe::heap()->object_iterate(&fic); } diff --git a/src/share/vm/memory/space.cpp b/src/share/vm/memory/space.cpp index 652d585bb..cad7f6828 100644 --- a/src/share/vm/memory/space.cpp +++ b/src/share/vm/memory/space.cpp @@ -705,6 +705,12 @@ void ContiguousSpace::object_iterate(ObjectClosure* blk) { object_iterate_from(bm, blk); } +// For a continguous space object_iterate() and safe_object_iterate() +// are the same. +void ContiguousSpace::safe_object_iterate(ObjectClosure* blk) { + object_iterate(blk); +} + void ContiguousSpace::object_iterate_from(WaterMark mark, ObjectClosure* blk) { assert(mark.space() == this, "Mark does not match space"); HeapWord* p = mark.point(); diff --git a/src/share/vm/memory/space.hpp b/src/share/vm/memory/space.hpp index a102c5f22..f055638e8 100644 --- a/src/share/vm/memory/space.hpp +++ b/src/share/vm/memory/space.hpp @@ -193,6 +193,9 @@ class Space: public CHeapObj { // each. Objects allocated by applications of the closure are not // included in the iteration. virtual void object_iterate(ObjectClosure* blk) = 0; + // Similar to object_iterate() except only iterates over + // objects whose internal references point to objects in the space. + virtual void safe_object_iterate(ObjectClosure* blk) = 0; // Iterate over all objects that intersect with mr, calling "cl->do_object" // on each. There is an exception to this: if this closure has already @@ -843,6 +846,9 @@ class ContiguousSpace: public CompactibleSpace { void oop_iterate(OopClosure* cl); void oop_iterate(MemRegion mr, OopClosure* cl); void object_iterate(ObjectClosure* blk); + // For contiguous spaces this method will iterate safely over objects + // in the space (i.e., between bottom and top) when at a safepoint. + void safe_object_iterate(ObjectClosure* blk); void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); // iterates on objects up to the safe limit HeapWord* object_iterate_careful(ObjectClosureCareful* cl); diff --git a/src/share/vm/prims/jvmtiTagMap.cpp b/src/share/vm/prims/jvmtiTagMap.cpp index 152789815..dcf83bb22 100644 --- a/src/share/vm/prims/jvmtiTagMap.cpp +++ b/src/share/vm/prims/jvmtiTagMap.cpp @@ -1320,6 +1320,9 @@ class VM_HeapIterateOperation: public VM_Operation { } // do the iteration + // If this operation encounters a bad object when using CMS, + // consider using safe_object_iterate() which avoids perm gen + // objects that may contain bad references. Universe::heap()->object_iterate(_blk); // when sharing is enabled we must iterate over the shared spaces diff --git a/src/share/vm/services/heapDumper.cpp b/src/share/vm/services/heapDumper.cpp index bf7aaf1a9..18bd9f477 100644 --- a/src/share/vm/services/heapDumper.cpp +++ b/src/share/vm/services/heapDumper.cpp @@ -1700,7 +1700,7 @@ void VM_HeapDumper::doit() { // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk // of the heap dump. HeapObjectDumper obj_dumper(this, writer()); - Universe::heap()->object_iterate(&obj_dumper); + Universe::heap()->safe_object_iterate(&obj_dumper); // HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals do_threads(); -- GitLab