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
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Fri Jan 30 14:17:52 2009 -0800
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Sat Jan 31 00:15:00 2009 -0800
@@ -42,6 +42,7 @@
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 @@
// 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 @@
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 {
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Fri Jan 30 14:17:52 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Sat Jan 31 00:15:00 2009 -0800
@@ -48,9 +48,14 @@
// 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);
}
--- a/hotspot/src/share/vm/memory/oopFactory.cpp Fri Jan 30 14:17:52 2009 -0800
+++ b/hotspot/src/share/vm/memory/oopFactory.cpp Sat Jan 31 00:15:00 2009 -0800
@@ -90,9 +90,11 @@
}
-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);
}
--- a/hotspot/src/share/vm/memory/oopFactory.hpp Fri Jan 30 14:17:52 2009 -0800
+++ b/hotspot/src/share/vm/memory/oopFactory.hpp Sat Jan 31 00:15:00 2009 -0800
@@ -84,7 +84,9 @@
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,
--- a/hotspot/src/share/vm/oops/cpCacheKlass.cpp Fri Jan 30 14:17:52 2009 -0800
+++ b/hotspot/src/share/vm/oops/cpCacheKlass.cpp Sat Jan 31 00:15:00 2009 -0800
@@ -32,13 +32,43 @@
}
-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 @@
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 @@
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) {
--- a/hotspot/src/share/vm/oops/cpCacheKlass.hpp Fri Jan 30 14:17:52 2009 -0800
+++ b/hotspot/src/share/vm/oops/cpCacheKlass.hpp Sat Jan 31 00:15:00 2009 -0800
@@ -32,7 +32,7 @@
// 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 @@
// 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
--- a/hotspot/src/share/vm/oops/cpCacheOop.hpp Fri Jan 30 14:17:52 2009 -0800
+++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp Sat Jan 31 00:15:00 2009 -0800
@@ -291,6 +291,9 @@
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 @@
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)); }