hotspot/src/share/vm/oops/constantPoolOop.hpp
changeset 8076 96d498ec7ae1
parent 7436 dbc43da3d512
child 8107 78e5bd944384
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp	Thu Jan 27 13:42:28 2011 -0800
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp	Thu Jan 27 16:11:27 2011 -0800
@@ -27,6 +27,7 @@
 
 #include "oops/arrayOop.hpp"
 #include "oops/cpCacheOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "utilities/constantTag.hpp"
 #ifdef TARGET_ARCH_x86
@@ -47,10 +48,32 @@
 // modified when the entry is resolved.  If a klass or string constant pool
 // entry is read without a lock, only the resolved state guarantees that
 // the entry in the constant pool is a klass or String object and
-// not a symbolOop.
+// not a Symbol*.
 
 class SymbolHashMap;
 
+class CPSlot VALUE_OBJ_CLASS_SPEC {
+  intptr_t _ptr;
+ public:
+  CPSlot(intptr_t ptr): _ptr(ptr) {}
+  CPSlot(void* ptr): _ptr((intptr_t)ptr) {}
+  CPSlot(oop ptr): _ptr((intptr_t)ptr) {}
+  CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | 1) {}
+
+  intptr_t value()   { return _ptr; }
+  bool is_oop()      { return (_ptr & 1) == 0; }
+  bool is_metadata() { return (_ptr & 1) == 1; }
+
+  oop get_oop() {
+    assert(is_oop(), "bad call");
+    return oop(_ptr);
+  }
+  Symbol* get_symbol() {
+    assert(is_metadata(), "bad call");
+    return (Symbol*)(_ptr & ~1);
+  }
+};
+
 class constantPoolOopDesc : public oopDesc {
   friend class VMStructs;
   friend class BytecodeInterpreter;  // Directly extracts an oop in the pool for fast instanceof/checkcast
@@ -89,11 +112,41 @@
   oop* cache_addr()      { return (oop*)&_cache; }
   oop* operands_addr()   { return (oop*)&_operands; }
 
-  oop* obj_at_addr(int which) const {
+  CPSlot slot_at(int which) {
+    assert(is_within_bounds(which), "index out of bounds");
+    // There's a transitional value of zero when converting from
+    // Symbol->0->Klass for G1 when resolving classes and strings.
+    // wait for the value to be non-zero (this is temporary)
+    volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
+    if (adr == 0 && which != 0) {
+      constantTag t = tag_at(which);
+      if (t.is_unresolved_klass() || t.is_klass() ||
+          t.is_unresolved_string() || t.is_string()) {
+        while ((adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))) == 0);
+      }
+    }
+    return CPSlot(adr);
+  }
+
+  void slot_at_put(int which, CPSlot s) const {
+    assert(is_within_bounds(which), "index out of bounds");
+    *(intptr_t*)&base()[which] = s.value();
+  }
+  oop* obj_at_addr_raw(int which) const {
     assert(is_within_bounds(which), "index out of bounds");
     return (oop*) &base()[which];
   }
 
+  void obj_at_put_without_check(int which, oop o) {
+    assert(is_within_bounds(which), "index out of bounds");
+    oop_store_without_check((volatile oop *)obj_at_addr_raw(which), o);
+  }
+
+  void obj_at_put(int which, oop o) const {
+    assert(is_within_bounds(which), "index out of bounds");
+    oop_store((volatile oop*)obj_at_addr_raw(which), o);
+  }
+
   jint* int_at_addr(int which) const {
     assert(is_within_bounds(which), "index out of bounds");
     return (jint*) &base()[which];
@@ -141,15 +194,20 @@
   // Storing constants
 
   void klass_at_put(int which, klassOop k) {
-    oop_store_without_check((volatile oop *)obj_at_addr(which), oop(k));
+    // Overwrite the old index with a GC friendly value so
+    // that if G1 looks during the transition during oop_store it won't
+    // assert the symbol is not an oop.
+    *obj_at_addr_raw(which) = NULL;
+    assert(k != NULL, "resolved class shouldn't be null");
+    obj_at_put_without_check(which, k);
     // The interpreter assumes when the tag is stored, the klass is resolved
-    // and the klassOop is a klass rather than a symbolOop, so we need
+    // and the klassOop is a klass rather than a Symbol*, so we need
     // hardware store ordering here.
     release_tag_at_put(which, JVM_CONSTANT_Class);
     if (UseConcMarkSweepGC) {
       // In case the earlier card-mark was consumed by a concurrent
       // marking thread before the tag was updated, redirty the card.
-      oop_store_without_check((volatile oop *)obj_at_addr(which), oop(k));
+      obj_at_put_without_check(which, k);
     }
   }
 
@@ -160,13 +218,9 @@
   }
 
   // Temporary until actual use
-  void unresolved_klass_at_put(int which, symbolOop s) {
-    // Overwrite the old index with a GC friendly value so
-    // that if GC looks during the transition it won't try
-    // to treat a small integer as oop.
-    *obj_at_addr(which) = NULL;
+  void unresolved_klass_at_put(int which, Symbol* s) {
     release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
-    oop_store_without_check(obj_at_addr(which), oop(s));
+    slot_at_put(which, s);
   }
 
   void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
@@ -191,10 +245,9 @@
   }
 
   // Temporary until actual use
-  void unresolved_string_at_put(int which, symbolOop s) {
-    *obj_at_addr(which) = NULL;
+  void unresolved_string_at_put(int which, Symbol* s) {
     release_tag_at_put(which, JVM_CONSTANT_UnresolvedString);
-    oop_store_without_check(obj_at_addr(which), oop(s));
+    slot_at_put(which, s);
   }
 
   void int_at_put(int which, jint i) {
@@ -220,28 +273,39 @@
     Bytes::put_native_u8((address) double_at_addr(which), *((u8*) &d));
   }
 
-  void symbol_at_put(int which, symbolOop s) {
+  Symbol** symbol_at_addr(int which) const {
+    assert(is_within_bounds(which), "index out of bounds");
+    return (Symbol**) &base()[which];
+  }
+
+  void symbol_at_put(int which, Symbol* s) {
+    assert(s->refcount() != 0, "should have nonzero refcount");
     tag_at_put(which, JVM_CONSTANT_Utf8);
-    oop_store_without_check(obj_at_addr(which), oop(s));
+    slot_at_put(which, s);
   }
 
   void string_at_put(int which, oop str) {
-    oop_store((volatile oop*)obj_at_addr(which), str);
+    // Overwrite the old index with a GC friendly value so
+    // that if G1 looks during the transition during oop_store it won't
+    // assert the symbol is not an oop.
+    *obj_at_addr_raw(which) = NULL;
+    assert(str != NULL, "resolved string shouldn't be null");
+    obj_at_put(which, str);
     release_tag_at_put(which, JVM_CONSTANT_String);
     if (UseConcMarkSweepGC) {
       // In case the earlier card-mark was consumed by a concurrent
       // marking thread before the tag was updated, redirty the card.
-      oop_store_without_check((volatile oop *)obj_at_addr(which), str);
+      obj_at_put_without_check(which, str);
     }
   }
 
   void object_at_put(int which, oop str) {
-    oop_store((volatile oop*) obj_at_addr(which), str);
+    obj_at_put(which, str);
     release_tag_at_put(which, JVM_CONSTANT_Object);
     if (UseConcMarkSweepGC) {
       // In case the earlier card-mark was consumed by a concurrent
       // marking thread before the tag was updated, redirty the card.
-      oop_store_without_check((volatile oop*) obj_at_addr(which), str);
+      obj_at_put_without_check(which, str);
     }
   }
 
@@ -279,13 +343,19 @@
   bool is_pointer_entry(int which) {
     constantTag tag = tag_at(which);
     return tag.is_klass() ||
-      tag.is_unresolved_klass() ||
-      tag.is_symbol() ||
-      tag.is_unresolved_string() ||
       tag.is_string() ||
       tag.is_object();
   }
 
+  // Whether the entry points to an object for ldc (resolved or not)
+  bool is_object_entry(int which) {
+    constantTag tag = tag_at(which);
+    return is_pointer_entry(which) ||
+      tag.is_unresolved_klass() ||
+      tag.is_unresolved_string() ||
+      tag.is_symbol();
+  }
+
   // Fetching constants
 
   klassOop klass_at(int which, TRAPS) {
@@ -293,25 +363,25 @@
     return klass_at_impl(h_this, which, CHECK_NULL);
   }
 
-  symbolOop klass_name_at(int which);  // Returns the name, w/o resolving.
+  Symbol* klass_name_at(int which);  // Returns the name, w/o resolving.
 
   klassOop resolved_klass_at(int which) {  // Used by Compiler
     guarantee(tag_at(which).is_klass(), "Corrupted constant pool");
     // Must do an acquire here in case another thread resolved the klass
     // behind our back, lest we later load stale values thru the oop.
-    return klassOop((oop)OrderAccess::load_ptr_acquire(obj_at_addr(which)));
+    return klassOop(CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_oop());
   }
 
   // This method should only be used with a cpool lock or during parsing or gc
-  symbolOop unresolved_klass_at(int which) {     // Temporary until actual use
-    symbolOop s = symbolOop((oop)OrderAccess::load_ptr_acquire(obj_at_addr(which)));
+  Symbol* unresolved_klass_at(int which) {     // Temporary until actual use
+    Symbol* s = CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol();
     // check that the klass is still unresolved.
     assert(tag_at(which).is_unresolved_klass(), "Corrupted constant pool");
     return s;
   }
 
   // RedefineClasses() API support:
-  symbolOop klass_at_noresolve(int which) { return klass_name_at(which); }
+  Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
 
   jint int_at(int which) {
     assert(tag_at(which).is_int(), "Corrupted constant pool");
@@ -336,9 +406,9 @@
     return *((jdouble*)&tmp);
   }
 
-  symbolOop symbol_at(int which) {
+  Symbol* symbol_at(int which) {
     assert(tag_at(which).is_utf8(), "Corrupted constant pool");
-    return symbolOop(*obj_at_addr(which));
+    return slot_at(which).get_symbol();
   }
 
   oop string_at(int which, TRAPS) {
@@ -348,7 +418,7 @@
 
   oop object_at(int which) {
     assert(tag_at(which).is_object(), "Corrupted constant pool");
-    return *obj_at_addr(which);
+    return slot_at(which).get_oop();
   }
 
   // A "pseudo-string" is an non-string oop that has found is way into
@@ -362,7 +432,7 @@
 
   oop pseudo_string_at(int which) {
     assert(tag_at(which).is_string(), "Corrupted constant pool");
-    return *obj_at_addr(which);
+    return slot_at(which).get_oop();
   }
 
   void pseudo_string_at_put(int which, oop x) {
@@ -378,12 +448,12 @@
     assert(tag_at(which).is_string(), "Corrupted constant pool");
     // Must do an acquire here in case another thread resolved the klass
     // behind our back, lest we later load stale values thru the oop.
-    return (oop)OrderAccess::load_ptr_acquire(obj_at_addr(which));
+    return CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_oop();
   }
 
   // This method should only be used with a cpool lock or during parsing or gc
-  symbolOop unresolved_string_at(int which) {    // Temporary until actual use
-    symbolOop s = symbolOop((oop)OrderAccess::load_ptr_acquire(obj_at_addr(which)));
+  Symbol* unresolved_string_at(int which) {    // Temporary until actual use
+    Symbol* s = CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol();
     // check that the string is still unresolved.
     assert(tag_at(which).is_unresolved_string(), "Corrupted constant pool");
     return s;
@@ -391,7 +461,7 @@
 
   // Returns an UTF8 for a CONSTANT_String entry at a given index.
   // UTF8 char* representation was chosen to avoid conversion of
-  // java_lang_Strings at resolved entries into symbolOops
+  // java_lang_Strings at resolved entries into Symbol*s
   // or vice versa.
   // Caller is responsible for checking for pseudo-strings.
   char* string_at_noresolve(int which);
@@ -414,11 +484,11 @@
     return *int_at_addr(which);
   }
   // Derived queries:
-  symbolOop method_handle_name_ref_at(int which) {
+  Symbol* method_handle_name_ref_at(int which) {
     int member = method_handle_index_at(which);
     return impl_name_ref_at(member, true);
   }
-  symbolOop method_handle_signature_ref_at(int which) {
+  Symbol* method_handle_signature_ref_at(int which) {
     int member = method_handle_index_at(which);
     return impl_signature_ref_at(member, true);
   }
@@ -426,7 +496,7 @@
     int member = method_handle_index_at(which);
     return impl_klass_ref_index_at(member, true);
   }
-  symbolOop method_type_signature_at(int which) {
+  Symbol* method_type_signature_at(int which) {
     int sym = method_type_index_at(which);
     return symbol_at(sym);
   }
@@ -534,9 +604,9 @@
 
   // Lookup for entries consisting of (klass_index, name_and_type index)
   klassOop klass_ref_at(int which, TRAPS);
-  symbolOop klass_ref_at_noresolve(int which);
-  symbolOop name_ref_at(int which)                { return impl_name_ref_at(which, false); }
-  symbolOop signature_ref_at(int which)           { return impl_signature_ref_at(which, false); }
+  Symbol* klass_ref_at_noresolve(int which);
+  Symbol* name_ref_at(int which)                { return impl_name_ref_at(which, false); }
+  Symbol* signature_ref_at(int which)           { return impl_signature_ref_at(which, false); }
 
   int klass_ref_index_at(int which)               { return impl_klass_ref_index_at(which, false); }
   int name_and_type_ref_index_at(int which)       { return impl_name_and_type_ref_index_at(which, false); }
@@ -605,15 +675,15 @@
   // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
   // future by other Java code. These take constant pool indices rather than
   // constant pool cache indices as do the peer methods above.
-  symbolOop uncached_klass_ref_at_noresolve(int which);
-  symbolOop uncached_name_ref_at(int which)                 { return impl_name_ref_at(which, true); }
-  symbolOop uncached_signature_ref_at(int which)            { return impl_signature_ref_at(which, true); }
+  Symbol* uncached_klass_ref_at_noresolve(int which);
+  Symbol* uncached_name_ref_at(int which)                 { return impl_name_ref_at(which, true); }
+  Symbol* uncached_signature_ref_at(int which)            { return impl_signature_ref_at(which, true); }
   int       uncached_klass_ref_index_at(int which)          { return impl_klass_ref_index_at(which, true); }
   int       uncached_name_and_type_ref_index_at(int which)  { return impl_name_and_type_ref_index_at(which, true); }
 
   // Sharing
   int pre_resolve_shared_klasses(TRAPS);
-  void shared_symbols_iterate(OopClosure* closure0);
+  void shared_symbols_iterate(SymbolClosure* closure0);
   void shared_tags_iterate(OopClosure* closure0);
   void shared_strings_iterate(OopClosure* closure0);
 
@@ -628,8 +698,8 @@
 
  private:
 
-  symbolOop impl_name_ref_at(int which, bool uncached);
-  symbolOop impl_signature_ref_at(int which, bool uncached);
+  Symbol* impl_name_ref_at(int which, bool uncached);
+  Symbol* impl_signature_ref_at(int which, bool uncached);
   int       impl_klass_ref_index_at(int which, bool uncached);
   int       impl_name_and_type_ref_index_at(int which, bool uncached);
 
@@ -672,6 +742,9 @@
   int  orig_length() const                { return _orig_length; }
   void set_orig_length(int orig_length)   { _orig_length = orig_length; }
 
+  // Decrease ref counts of symbols that are in the constant pool
+  // when the holder class is unloaded
+  void unreference_symbols();
 
   // JVMTI accesss - GetConstantPool, RetransformClasses, ...
   friend class JvmtiConstantPoolReconstituter;
@@ -694,7 +767,7 @@
  private:
   unsigned int        _hash;   // 32-bit hash for item
   SymbolHashMapEntry* _next;   // Next element in the linked list for this bucket
-  symbolOop           _symbol; // 1-st part of the mapping: symbol => value
+  Symbol*             _symbol; // 1-st part of the mapping: symbol => value
   u2                  _value;  // 2-nd part of the mapping: symbol => value
 
  public:
@@ -704,13 +777,13 @@
   SymbolHashMapEntry* next() const        { return _next;   }
   void set_next(SymbolHashMapEntry* next) { _next = next;   }
 
-  symbolOop  symbol() const               { return _symbol; }
-  void       set_symbol(symbolOop sym)    { _symbol = sym;  }
+  Symbol*    symbol() const               { return _symbol; }
+  void       set_symbol(Symbol* sym)      { _symbol = sym;  }
 
   u2         value() const                {  return _value; }
   void       set_value(u2 value)          { _value = value; }
 
-  SymbolHashMapEntry(unsigned int hash, symbolOop symbol, u2 value)
+  SymbolHashMapEntry(unsigned int hash, Symbol* symbol, u2 value)
     : _hash(hash), _symbol(symbol), _value(value), _next(NULL) {}
 
 }; // End SymbolHashMapEntry class
@@ -769,10 +842,10 @@
     return _buckets[i].entry();
   }
 
-  void add_entry(symbolOop sym, u2 value);
-  SymbolHashMapEntry* find_entry(symbolOop sym);
+  void add_entry(Symbol* sym, u2 value);
+  SymbolHashMapEntry* find_entry(Symbol* sym);
 
-  u2 symbol_to_value(symbolOop sym) {
+  u2 symbol_to_value(Symbol* sym) {
     SymbolHashMapEntry *entry = find_entry(sym);
     return (entry == NULL) ? 0 : entry->value();
   }