Mercurial > hg > graal-jvmci-8
diff src/share/vm/oops/constantPoolOop.hpp @ 2177:3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
Summary: move symbols from permgen into C heap and reference count them
Reviewed-by: never, acorn, jmasa, stefank
author | coleenp |
---|---|
date | Thu, 27 Jan 2011 16:11:27 -0800 |
parents | dad31fc330cd |
children | b92c45f2bc75 |
line wrap: on
line diff
--- a/src/share/vm/oops/constantPoolOop.hpp Thu Jan 27 13:42:28 2011 -0800 +++ b/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(); }