From e0b329bb040bf91420b671640a7a7bf169b6e22b Mon Sep 17 00:00:00 2001 From: jmasa Date: Sat, 31 Jan 2009 00:15:00 -0800 Subject: [PATCH] 6792421: assert(_bitMap->isMarked(addr+size-1),inconsistent Printezis mark) Summary: The CMS concurrent precleaning and concurrent marking phases should work around classes that are undergoing redefinition. Reviewed-by: ysr, tonyp --- src/share/vm/gc_interface/collectedHeap.hpp | 4 +- src/share/vm/interpreter/rewriter.cpp | 7 +++- src/share/vm/memory/oopFactory.cpp | 6 ++- src/share/vm/memory/oopFactory.hpp | 4 +- src/share/vm/oops/cpCacheKlass.cpp | 42 +++++++++++++++++++-- src/share/vm/oops/cpCacheKlass.hpp | 3 +- src/share/vm/oops/cpCacheOop.hpp | 9 +++++ 7 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/share/vm/gc_interface/collectedHeap.hpp b/src/share/vm/gc_interface/collectedHeap.hpp index 41d80a3a9..210e6b32b 100644 --- a/src/share/vm/gc_interface/collectedHeap.hpp +++ b/src/share/vm/gc_interface/collectedHeap.hpp @@ -42,6 +42,7 @@ class Thread; class CollectedHeap : public CHeapObj { friend class VMStructs; friend class IsGCActiveMark; // Block structured external access to _is_gc_active + friend class constantPoolCacheKlass; // allocate() method inserts is_conc_safe #ifdef ASSERT static int _fire_out_of_memory_count; @@ -82,8 +83,6 @@ class CollectedHeap : public CHeapObj { // Reinitialize tlabs before resuming mutators. virtual void resize_all_tlabs(); - debug_only(static void check_for_valid_allocation_state();) - protected: // Allocate from the current thread's TLAB, with broken-out slow path. inline static HeapWord* allocate_from_tlab(Thread* thread, size_t size); @@ -142,6 +141,7 @@ class CollectedHeap : public CHeapObj { PRODUCT_RETURN; virtual void check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) PRODUCT_RETURN; + debug_only(static void check_for_valid_allocation_state();) public: enum Name { diff --git a/src/share/vm/interpreter/rewriter.cpp b/src/share/vm/interpreter/rewriter.cpp index d000012b5..323ea8f9a 100644 --- a/src/share/vm/interpreter/rewriter.cpp +++ b/src/share/vm/interpreter/rewriter.cpp @@ -48,9 +48,14 @@ void Rewriter::compute_index_maps(constantPoolHandle pool, intArray*& index_map, // Creates a constant pool cache given an inverse_index_map +// This creates the constant pool cache initially in a state +// that is unsafe for concurrent GC processing but sets it to +// a safe mode before the constant pool cache is returned. constantPoolCacheHandle Rewriter::new_constant_pool_cache(intArray& inverse_index_map, TRAPS) { const int length = inverse_index_map.length(); - constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, CHECK_(constantPoolCacheHandle())); + constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, + methodOopDesc::IsUnsafeConc, + CHECK_(constantPoolCacheHandle())); cache->initialize(inverse_index_map); return constantPoolCacheHandle(THREAD, cache); } diff --git a/src/share/vm/memory/oopFactory.cpp b/src/share/vm/memory/oopFactory.cpp index 24c67634e..32bd1f822 100644 --- a/src/share/vm/memory/oopFactory.cpp +++ b/src/share/vm/memory/oopFactory.cpp @@ -90,9 +90,11 @@ constantPoolOop oopFactory::new_constantPool(int length, } -constantPoolCacheOop oopFactory::new_constantPoolCache(int length, TRAPS) { +constantPoolCacheOop oopFactory::new_constantPoolCache(int length, + bool is_conc_safe, + TRAPS) { constantPoolCacheKlass* ck = constantPoolCacheKlass::cast(Universe::constantPoolCacheKlassObj()); - return ck->allocate(length, CHECK_NULL); + return ck->allocate(length, is_conc_safe, CHECK_NULL); } diff --git a/src/share/vm/memory/oopFactory.hpp b/src/share/vm/memory/oopFactory.hpp index e5a80073b..a0db0f521 100644 --- a/src/share/vm/memory/oopFactory.hpp +++ b/src/share/vm/memory/oopFactory.hpp @@ -84,7 +84,9 @@ class oopFactory: AllStatic { static constantPoolOop new_constantPool (int length, bool is_conc_safe, TRAPS); - static constantPoolCacheOop new_constantPoolCache(int length, TRAPS); + static constantPoolCacheOop new_constantPoolCache(int length, + bool is_conc_safe, + TRAPS); // Instance classes static klassOop new_instanceKlass(int vtable_len, int itable_len, int static_field_size, diff --git a/src/share/vm/oops/cpCacheKlass.cpp b/src/share/vm/oops/cpCacheKlass.cpp index 241914dca..c71ecfd9f 100644 --- a/src/share/vm/oops/cpCacheKlass.cpp +++ b/src/share/vm/oops/cpCacheKlass.cpp @@ -32,13 +32,43 @@ int constantPoolCacheKlass::oop_size(oop obj) const { } -constantPoolCacheOop constantPoolCacheKlass::allocate(int length, TRAPS) { +constantPoolCacheOop constantPoolCacheKlass::allocate(int length, + bool is_conc_safe, + TRAPS) { // allocate memory int size = constantPoolCacheOopDesc::object_size(length); + KlassHandle klass (THREAD, as_klassOop()); - constantPoolCacheOop cache = (constantPoolCacheOop) - CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + + // This is the original code. The code from permanent_obj_allocate() + // was in-lined to allow the setting of is_conc_safe before the klass + // is installed. + // constantPoolCacheOop cache = (constantPoolCacheOop) + // CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + + oop obj = CollectedHeap::permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); + constantPoolCacheOop cache = (constantPoolCacheOop) obj; + cache->set_is_conc_safe(is_conc_safe); + // The store to is_conc_safe must be visible before the klass + // is set. This should be done safely because _is_conc_safe has + // been declared volatile. If there are any problems, consider adding + // OrderAccess::storestore(); + CollectedHeap::post_allocation_install_obj_klass(klass, obj, size); + NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, + size)); + + // The length field affects the size of the object. The allocation + // above allocates the correct size (see calculation of "size") but + // the size() method of the constant pool cache oop will not reflect + // that size until the correct length is set. cache->set_length(length); + + // The store of the length must be visible before is_conc_safe is + // set to a safe state. + // This should be done safely because _is_conc_safe has + // been declared volatile. If there are any problems, consider adding + // OrderAccess::storestore(); + cache->set_is_conc_safe(methodOopDesc::IsSafeConc); cache->set_constant_pool(NULL); return cache; } @@ -114,7 +144,6 @@ int constantPoolCacheKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegio return size; } - int constantPoolCacheKlass::oop_adjust_pointers(oop obj) { assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); constantPoolCacheOop cache = (constantPoolCacheOop)obj; @@ -131,6 +160,11 @@ int constantPoolCacheKlass::oop_adjust_pointers(oop obj) { return size; } +bool constantPoolCacheKlass::oop_is_conc_safe(oop obj) const { + assert(obj->is_constantPoolCache(), "must be constMethod oop"); + return constantPoolCacheOop(obj)->is_conc_safe(); +} + #ifndef SERIALGC void constantPoolCacheKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { diff --git a/src/share/vm/oops/cpCacheKlass.hpp b/src/share/vm/oops/cpCacheKlass.hpp index ea826671d..299910052 100644 --- a/src/share/vm/oops/cpCacheKlass.hpp +++ b/src/share/vm/oops/cpCacheKlass.hpp @@ -32,7 +32,7 @@ class constantPoolCacheKlass: public Klass { // Allocation DEFINE_ALLOCATE_PERMANENT(constantPoolCacheKlass); - constantPoolCacheOop allocate(int length, TRAPS); + constantPoolCacheOop allocate(int length, bool is_conc_safe, TRAPS); static klassOop create_klass(TRAPS); // Casting from klassOop @@ -48,6 +48,7 @@ class constantPoolCacheKlass: public Klass { // Garbage collection void oop_follow_contents(oop obj); int oop_adjust_pointers(oop obj); + virtual bool oop_is_conc_safe(oop obj) const; // Parallel Scavenge and Parallel Old PARALLEL_GC_DECLS diff --git a/src/share/vm/oops/cpCacheOop.hpp b/src/share/vm/oops/cpCacheOop.hpp index ccdb4472e..c5ba60521 100644 --- a/src/share/vm/oops/cpCacheOop.hpp +++ b/src/share/vm/oops/cpCacheOop.hpp @@ -291,6 +291,9 @@ class constantPoolCacheOopDesc: public oopDesc { private: int _length; constantPoolOop _constant_pool; // the corresponding constant pool + // If true, safe for concurrent GC processing, + // Set unconditionally in constantPoolCacheKlass::allocate() + volatile bool _is_conc_safe; // Sizing debug_only(friend class ClassVerifier;) @@ -316,6 +319,12 @@ class constantPoolCacheOopDesc: public oopDesc { constantPoolOop constant_pool() const { return _constant_pool; } ConstantPoolCacheEntry* entry_at(int i) const { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; } + // GC support + // If the _length field has not been set, the size of the + // constantPoolCache cannot be correctly calculated. + bool is_conc_safe() { return _is_conc_safe; } + void set_is_conc_safe(bool v) { _is_conc_safe = v; } + // Code generation static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); } -- GitLab