< prev index next >

src/share/vm/oops/constantPool.hpp

Print this page

*** 44,74 **** // the entry in the constant pool is a klass object and not a Symbol*. class SymbolHashMap; class CPSlot VALUE_OBJ_CLASS_SPEC { intptr_t _ptr; public: - enum TagBits { _resolved_value = 0, _symbol_bit = 1, _pseudo_bit = 2, _symbol_mask = 3 }; CPSlot(intptr_t ptr): _ptr(ptr) {} ! CPSlot(Klass* ptr): _ptr((intptr_t)ptr) {} ! CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | _symbol_bit) {} ! CPSlot(Symbol* ptr, int tag_bits): _ptr((intptr_t)ptr | tag_bits) {} intptr_t value() { return _ptr; } ! bool is_resolved() { return (_ptr & _symbol_bit ) == _resolved_value; } ! bool is_unresolved() { return (_ptr & _symbol_bit ) != _resolved_value; } ! bool is_pseudo_string() { return (_ptr & _symbol_mask) == _symbol_bit + _pseudo_bit; } Symbol* get_symbol() { ! assert(is_unresolved(), "bad call"); ! return (Symbol*)(_ptr & ~_symbol_mask); } ! Klass* get_klass() { ! assert(is_resolved(), "bad call"); ! return (Klass*)_ptr; } }; class KlassSizeStats; --- 44,94 ---- // the entry in the constant pool is a klass object and not a Symbol*. class SymbolHashMap; class CPSlot VALUE_OBJ_CLASS_SPEC { + friend class ConstantPool; intptr_t _ptr; + enum TagBits {_pseudo_bit = 1}; public: CPSlot(intptr_t ptr): _ptr(ptr) {} ! CPSlot(Symbol* ptr, int tag_bits = 0): _ptr((intptr_t)ptr | tag_bits) {} intptr_t value() { return _ptr; } ! bool is_pseudo_string() { return (_ptr & _pseudo_bit) != 0; } Symbol* get_symbol() { ! return (Symbol*)(_ptr & ~_pseudo_bit); } ! }; ! ! // This represents a JVM_CONSTANT_Class, JVM_CONSTANT_UnresolvedClass, or ! // JVM_CONSTANT_UnresolvedClassInError slot in the constant pool. ! class CPKlassSlot VALUE_OBJ_CLASS_SPEC { ! // cp->symbol_at(_name_index) gives the name of the class. ! int _name_index; ! ! // cp->_resolved_klasses->at(_resolved_klass_index) gives the Klass* for the class. ! int _resolved_klass_index; ! public: ! enum { ! // This is used during constant pool merging where the resolved klass index is ! // not yet known, and will be computed at a later stage (during a call to ! // initialize_unresolved_klasses()). ! _temp_resolved_klass_index = 0xffff ! }; ! CPKlassSlot(int n, int rk) { ! _name_index = n; ! _resolved_klass_index = rk; ! } ! int name_index() const { ! return _name_index; ! } ! int resolved_klass_index() const { ! assert(_resolved_klass_index != _temp_resolved_klass_index, "constant pool merging was incomplete"); ! return _resolved_klass_index; } }; class KlassSizeStats;
*** 81,98 **** Array<u1>* _tags; // the tag array describing the constant pool's contents ConstantPoolCache* _cache; // the cache holding interpreter runtime information InstanceKlass* _pool_holder; // the corresponding class Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty ! // Array of resolved objects from the constant pool and map from resolved ! // object index to original constant pool index ! jobject _resolved_references; ! Array<u2>* _reference_map; enum { _has_preresolution = 1, // Flags ! _on_stack = 2 }; int _flags; // old fashioned bit twiddling int _length; // number of elements in the array --- 101,117 ---- Array<u1>* _tags; // the tag array describing the constant pool's contents ConstantPoolCache* _cache; // the cache holding interpreter runtime information InstanceKlass* _pool_holder; // the corresponding class Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty ! // ... will be changed to support compressed pointers ! Array<Klass*>* _resolved_klasses; enum { _has_preresolution = 1, // Flags ! _on_stack = 2, ! _is_shared = 4 }; int _flags; // old fashioned bit twiddling int _length; // number of elements in the array
*** 117,126 **** --- 136,146 ---- private: intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); } CPSlot slot_at(int which) const { assert(is_within_bounds(which), "index out of bounds"); + assert(!tag_at(which).is_unresolved_klass() && !tag_at(which).is_unresolved_klass_in_error(), "Corrupted constant pool"); // Uses volatile because the klass slot changes without a lock. volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which)); assert(adr != 0 || which == 0, "cp entry for klass should not be zero"); return CPSlot(adr); }
*** 164,182 **** Array<u1>* tags() const { return _tags; } Array<u2>* operands() const { return _operands; } bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } ! void set_has_preresolution() { _flags |= _has_preresolution; } // Redefine classes support. If a method refering to this constant pool // is on the executing stack, or as a handle in vm code, this constant pool // can't be removed from the set of previous versions saved in the instance // class. bool on_stack() const { return (_flags &_on_stack) != 0; } void set_on_stack(const bool value); // Klass holding pool InstanceKlass* pool_holder() const { return _pool_holder; } void set_pool_holder(InstanceKlass* k) { _pool_holder = k; } InstanceKlass** pool_holder_addr() { return &_pool_holder; } --- 184,208 ---- Array<u1>* tags() const { return _tags; } Array<u2>* operands() const { return _operands; } bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } ! void set_has_preresolution() { ! assert(!is_shared(), "should never be called on shared ConstantPools"); ! _flags |= _has_preresolution; ! } // Redefine classes support. If a method refering to this constant pool // is on the executing stack, or as a handle in vm code, this constant pool // can't be removed from the set of previous versions saved in the instance // class. bool on_stack() const { return (_flags &_on_stack) != 0; } void set_on_stack(const bool value); + // Faster than MetaspaceObj::is_shared() - used by set_on_stack() + bool is_shared() const { return (_flags & _is_shared) != 0; } + // Klass holding pool InstanceKlass* pool_holder() const { return _pool_holder; } void set_pool_holder(InstanceKlass* k) { _pool_holder = k; } InstanceKlass** pool_holder_addr() { return &_pool_holder; }
*** 191,203 **** TRAPS); // resolved strings, methodHandles and callsite objects from the constant pool objArrayOop resolved_references() const; // mapping resolved object array indexes to cp indexes and back. ! int object_to_cp_index(int index) { return _reference_map->at(index); } int cp_to_object_index(int index); // Invokedynamic indexes. // They must look completely different from normal indexes. // The main reason is that byte swapping is sometimes done on normal indexes. // Finally, it is helpful for debugging to tell the two apart. static bool is_invokedynamic_index(int i) { return (i < 0); } --- 217,234 ---- TRAPS); // resolved strings, methodHandles and callsite objects from the constant pool objArrayOop resolved_references() const; // mapping resolved object array indexes to cp indexes and back. ! int object_to_cp_index(int index) { return reference_map()->at(index); } int cp_to_object_index(int index); + void set_resolved_klasses(Array<Klass*>* rk) { _resolved_klasses = rk; } + Array<Klass*>* resolved_klasses() const { return _resolved_klasses; } + void allocate_resolved_klasses(ClassLoaderData* loader_data, int num_klasses, TRAPS); + void initialize_unresolved_klasses(ClassLoaderData* loader_data, TRAPS); + // Invokedynamic indexes. // They must look completely different from normal indexes. // The main reason is that byte swapping is sometimes done on normal indexes. // Finally, it is helpful for debugging to tell the two apart. static bool is_invokedynamic_index(int i) { return (i < 0); }
*** 221,254 **** // Assembly code support static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); } static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); } static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); } ! static int resolved_references_offset_in_bytes() { return offset_of(ConstantPool, _resolved_references); } // Storing constants - void klass_at_put(int which, Klass* k) { - assert(k != NULL, "resolved class shouldn't be null"); - assert(is_within_bounds(which), "index out of bounds"); - OrderAccess::release_store_ptr((Klass* volatile *)obj_at_addr_raw(which), k); - // The interpreter assumes when the tag is stored, the klass is resolved - // and the Klass* is a klass rather than a Symbol*, so we need - // hardware store ordering here. - release_tag_at_put(which, JVM_CONSTANT_Class); - } - // For temporary use while constructing constant pool void klass_index_at_put(int which, int name_index) { tag_at_put(which, JVM_CONSTANT_ClassIndex); *int_at_addr(which) = name_index; } ! // Temporary until actual use ! void unresolved_klass_at_put(int which, Symbol* s) { release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass); ! slot_at_put(which, s); } void method_handle_index_at_put(int which, int ref_kind, int ref_index) { tag_at_put(which, JVM_CONSTANT_MethodHandle); *int_at_addr(which) = ((jint) ref_index<<16) | ref_kind; --- 252,282 ---- // Assembly code support static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); } static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); } static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); } ! static int resolved_klasses_offset_in_bytes() { return offset_of(ConstantPool, _resolved_klasses); } // Storing constants // For temporary use while constructing constant pool void klass_index_at_put(int which, int name_index) { tag_at_put(which, JVM_CONSTANT_ClassIndex); *int_at_addr(which) = name_index; } ! // Anonymous class support: ! void klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name); ! void klass_at_put(int class_index, Klass* k); ! ! void unresolved_klass_at_put(int which, int name_index, int resolved_klass_index) { release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass); ! ! assert((name_index & 0xffff0000) == 0, "must be"); ! assert((resolved_klass_index & 0xffff0000) == 0, "must be"); ! *int_at_addr(which) = ! build_int_from_shorts((jushort)resolved_klass_index, (jushort)name_index); } void method_handle_index_at_put(int which, int ref_kind, int ref_index) { tag_at_put(which, JVM_CONSTANT_MethodHandle); *int_at_addr(which) = ((jint) ref_index<<16) | ref_kind;
*** 264,274 **** *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index; } void unresolved_string_at_put(int which, Symbol* s) { release_tag_at_put(which, JVM_CONSTANT_String); ! slot_at_put(which, CPSlot(s, CPSlot::_symbol_bit)); } void int_at_put(int which, jint i) { tag_at_put(which, JVM_CONSTANT_Integer); *int_at_addr(which) = i; --- 292,302 ---- *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index; } void unresolved_string_at_put(int which, Symbol* s) { release_tag_at_put(which, JVM_CONSTANT_String); ! slot_at_put(which, CPSlot(s)); } void int_at_put(int which, jint i) { tag_at_put(which, JVM_CONSTANT_Integer); *int_at_addr(which) = i;
*** 346,366 **** Klass* klass_at_ignore_error(int which, TRAPS) { constantPoolHandle h_this(THREAD, this); return klass_at_impl(h_this, which, false, THREAD); } Symbol* klass_name_at(int which) const; // Returns the name, w/o resolving. Klass* resolved_klass_at(int which) const { // 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 CPSlot((Klass*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_klass(); } // RedefineClasses() API support: 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"); return *int_at_addr(which); } --- 374,415 ---- Klass* klass_at_ignore_error(int which, TRAPS) { constantPoolHandle h_this(THREAD, this); return klass_at_impl(h_this, which, false, THREAD); } + CPKlassSlot klass_slot_at(int which) const { + assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(), + "Corrupted constant pool"); + int value = *int_at_addr(which); + int name_index = extract_high_short_from_int(value); + int resolved_klass_index = extract_low_short_from_int(value); + return CPKlassSlot(name_index, resolved_klass_index); + } + Symbol* klass_name_at(int which) const; // Returns the name, w/o resolving. + int klass_name_index_at(int which) const { + return klass_slot_at(which).name_index(); + } Klass* resolved_klass_at(int which) const { // 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. ! CPKlassSlot kslot = klass_slot_at(which); ! assert(tag_at(kslot.name_index()).is_symbol(), "sanity"); ! ! Klass** adr = resolved_klasses()->adr_at(kslot.resolved_klass_index()); ! return (Klass*)OrderAccess::load_ptr_acquire(adr); } // RedefineClasses() API support: Symbol* klass_at_noresolve(int which) { return klass_name_at(which); } + void temp_unresolved_klass_at_put(int which, int name_index) { + // Used only during constant pool merging for class redefinition. The resolved klass index + // will be initialized later by a call to initialize_unresolved_klasses(). + unresolved_klass_at_put(which, name_index, CPKlassSlot::_temp_resolved_klass_index); + } jint int_at(int which) { assert(tag_at(which).is_int(), "Corrupted constant pool"); return *int_at_addr(which); }
*** 426,436 **** } void pseudo_string_at_put(int which, int obj_index, oop x) { assert(tag_at(which).is_string(), "Corrupted constant pool"); Symbol* sym = unresolved_string_at(which); ! slot_at_put(which, CPSlot(sym, (CPSlot::_symbol_bit | CPSlot::_pseudo_bit))); string_at_put(which, obj_index, x); // this works just fine } // only called when we are sure a string entry is already resolved (via an // earlier string_at call. --- 475,485 ---- } void pseudo_string_at_put(int which, int obj_index, oop x) { assert(tag_at(which).is_string(), "Corrupted constant pool"); Symbol* sym = unresolved_string_at(which); ! slot_at_put(which, CPSlot(sym, CPSlot::_pseudo_bit)); string_at_put(which, obj_index, x); // this works just fine } // only called when we are sure a string entry is already resolved (via an // earlier string_at call.
*** 757,769 **** return raw_index - CPCACHE_INDEX_TAG; } private: ! void set_resolved_references(jobject s) { _resolved_references = s; } ! Array<u2>* reference_map() const { return _reference_map; } ! void set_reference_map(Array<u2>* o) { _reference_map = o; } // patch JSR 292 resolved references after the class is linked. void patch_resolved_references(GrowableArray<Handle>* cp_patches); Symbol* impl_name_ref_at(int which, bool uncached); --- 806,818 ---- return raw_index - CPCACHE_INDEX_TAG; } private: ! void set_resolved_references(jobject s) { _cache->set_resolved_references(s); } ! Array<u2>* reference_map() const { return (_cache == NULL) ? NULL : _cache->reference_map(); } ! void set_reference_map(Array<u2>* o) { _cache->set_reference_map(o); } // patch JSR 292 resolved references after the class is linked. void patch_resolved_references(GrowableArray<Handle>* cp_patches); Symbol* impl_name_ref_at(int which, bool uncached);
< prev index next >