changeset 574:9a25e0c45327

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
author jmasa
date Sat, 31 Jan 2009 00:15:00 -0800
parents 23673011938d
children a268411445d9
files src/share/vm/gc_interface/collectedHeap.hpp src/share/vm/interpreter/rewriter.cpp src/share/vm/memory/oopFactory.cpp src/share/vm/memory/oopFactory.hpp src/share/vm/oops/cpCacheKlass.cpp src/share/vm/oops/cpCacheKlass.hpp src/share/vm/oops/cpCacheOop.hpp
diffstat 7 files changed, 64 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Fri Jan 30 14:17:52 2009 -0800
+++ b/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/src/share/vm/interpreter/rewriter.cpp	Fri Jan 30 14:17:52 2009 -0800
+++ b/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/src/share/vm/memory/oopFactory.cpp	Fri Jan 30 14:17:52 2009 -0800
+++ b/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/src/share/vm/memory/oopFactory.hpp	Fri Jan 30 14:17:52 2009 -0800
+++ b/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/src/share/vm/oops/cpCacheKlass.cpp	Fri Jan 30 14:17:52 2009 -0800
+++ b/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/src/share/vm/oops/cpCacheKlass.hpp	Fri Jan 30 14:17:52 2009 -0800
+++ b/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/src/share/vm/oops/cpCacheOop.hpp	Fri Jan 30 14:17:52 2009 -0800
+++ b/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)); }