--- old/src/share/vm/memory/metaspaceShared.hpp 2017-04-13 01:29:58.287127935 -0700 +++ new/src/share/vm/memory/metaspaceShared.hpp 2017-04-13 01:29:58.107121137 -0700 @@ -35,8 +35,8 @@ #define DEFAULT_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M)) #define MIN_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M)) -#define DEFAULT_SHARED_READ_ONLY_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M)) -#define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M)) +#define DEFAULT_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(13*M)) +#define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(13*M)) // the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on // the sizes required for dumping the archive using the default classlist. The sizes @@ -61,8 +61,8 @@ #define LargeSharedArchiveSize (300*M) #define HugeSharedArchiveSize (800*M) -#define ReadOnlyRegionPercentage 0.4 -#define ReadWriteRegionPercentage 0.55 +#define ReadOnlyRegionPercentage 0.52 +#define ReadWriteRegionPercentage 0.43 #define MiscDataRegionPercentage 0.03 #define MiscCodeRegionPercentage 0.02 #define LargeThresholdClassCount 5000 --- old/src/share/vm/oops/constantPool.cpp 2017-04-13 01:29:59.167161167 -0700 +++ new/src/share/vm/oops/constantPool.cpp 2017-04-13 01:29:58.971153765 -0700 @@ -47,8 +47,7 @@ #include "utilities/copy.hpp" ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) { - // Add one extra element to tags for storing ConstantPool::flags(). - Array* tags = MetadataFactory::new_writeable_array(loader_data, length+1, 0, CHECK_NULL); + Array* tags = MetadataFactory::new_writeable_array(loader_data, length, 0, CHECK_NULL); int size = ConstantPool::size(length); return new (loader_data, size, true, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags); } @@ -72,10 +71,10 @@ ConstantPool::ConstantPool(Array* tags) : _tags(tags), - _length(tags->length()-1) { + _length(tags->length()) { assert(_tags != NULL, "invariant"); - assert(tags->length()-1 == _length, "invariant"); // tags->at(_length) is flags() + assert(tags->length() == _length, "invariant"); assert(tag_array_is_zero_initialized(tags), "invariant"); assert(0 == flags(), "invariant"); assert(0 == version(), "invariant"); @@ -207,7 +206,7 @@ void ConstantPool::restore_unshareable_info(TRAPS) { assert(is_constantPool(), "ensure C++ vtable is restored"); assert(on_stack(), "should always be set for shared constant pools"); - assert(is_shared_quick(), "should always be set for shared constant pools"); + assert(is_shared(), "should always be set for shared constant pools"); // Only create the new resolved references array if it hasn't been attempted before if (resolved_references() != NULL) return; @@ -240,7 +239,7 @@ // The _on_stack flag is used to prevent ConstantPools from deallocation during // class redefinition. Since shared ConstantPools cannot be deallocated anyway, // we always set _on_stack to true to avoid having to change _flags during runtime. - _flags |= (_on_stack | _is_shared_quick); + _flags |= (_on_stack | _is_shared); } int ConstantPool::cp_to_object_index(int cp_index) { @@ -290,9 +289,9 @@ // A resolved constantPool entry will contain a Klass*, otherwise a Symbol*. // It is not safe to rely on the tag bit's here, since we don't have a lock, and // the entry and tag is not updated atomicly. - int value = *this_cp->int_at_addr(which); - int resolved_klass_index = extract_low_short_from_int(value); - int name_index = extract_high_short_from_int(value); + CPKlassSlot kslot = this_cp->klass_slot_at(which); + int resolved_klass_index = kslot.resolved_klass_index(); + int name_index = kslot.name_index(); assert(this_cp->tag_at(name_index).is_symbol(), "sanity"); Klass* klass = this_cp->resolved_klasses()->at(resolved_klass_index); @@ -353,7 +352,7 @@ Klass** adr = this_cp->resolved_klasses()->adr_at(resolved_klass_index); OrderAccess::release_store_ptr((Klass* volatile *)adr, 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 + // and the Klass* stored in _resolved_klasses is non-NULL, so we need // hardware store ordering here. this_cp->release_tag_at_put(which, JVM_CONSTANT_Class); return k; @@ -365,9 +364,9 @@ // instanceof operations. Returns NULL if the class has not been loaded or // if the verification of constant pool failed Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int which) { - int value = *this_cp->int_at_addr(which); - int resolved_klass_index = extract_low_short_from_int(value); - int name_index = extract_high_short_from_int(value); + CPKlassSlot kslot = this_cp->klass_slot_at(which); + int resolved_klass_index = kslot.resolved_klass_index(); + int name_index = kslot.name_index(); assert(this_cp->tag_at(name_index).is_symbol(), "sanity"); Klass* k = this_cp->resolved_klasses()->at(resolved_klass_index); @@ -553,19 +552,8 @@ return klass_at(klass_ref_index_at(which), THREAD); } - Symbol* ConstantPool::klass_name_at(int which) const { - assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(), - "Corrupted constant pool"); - int name_index = extract_high_short_from_int(*int_at_addr(which)); - return symbol_at(name_index); -} - -int ConstantPool::klass_name_index_at(int which) const { - assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(), - "Corrupted constant pool"); - int name_index = extract_high_short_from_int(*int_at_addr(which)); - return name_index; + return symbol_at(klass_slot_at(which).name_index()); } Symbol* ConstantPool::klass_ref_at_noresolve(int which) { @@ -1370,7 +1358,7 @@ case JVM_CONSTANT_UnresolvedClassInError: { // Revert to JVM_CONSTANT_ClassIndex - int name_index = extract_high_short_from_int(*from_cp->int_at_addr(from_i)); + int name_index = from_cp->klass_slot_at(from_i).name_index(); assert(from_cp->tag_at(name_index).is_symbol(), "sanity"); to_cp->klass_index_at_put(to_i, name_index); } break; @@ -1879,13 +1867,13 @@ if (value) { // Only record if it's not already set. if (!on_stack()) { - assert(!is_shared_quick(), "should always be set for shared constant pools"); + assert(!is_shared(), "should always be set for shared constant pools"); _flags |= _on_stack; MetadataOnStackMark::record(this); } } else { // Clearing is done single-threadedly. - if (!is_shared_quick()) { + if (!is_shared()) { _flags &= ~_on_stack; } } @@ -2033,9 +2021,9 @@ break; case JVM_CONSTANT_UnresolvedClass : // fall-through case JVM_CONSTANT_UnresolvedClassInError: { - int value = *int_at_addr(index); - int resolved_klass_index = extract_low_short_from_int(value); - int name_index = extract_high_short_from_int(value); + CPKlassSlot kslot = klass_slot_at(index); + int resolved_klass_index = kslot.resolved_klass_index(); + int name_index = kslot.name_index(); assert(tag_at(name_index).is_symbol(), "sanity"); Klass* klass = resolved_klasses()->at(resolved_klass_index); --- old/src/share/vm/oops/constantPool.hpp 2017-04-13 01:30:00.095196213 -0700 +++ new/src/share/vm/oops/constantPool.hpp 2017-04-13 01:29:59.907189113 -0700 @@ -62,6 +62,22 @@ } }; +class CPKlassSlot VALUE_OBJ_CLASS_SPEC { + int _name_index; + int _resolved_klass_index; +public: + CPKlassSlot(int n, int rk) { + _name_index = n; + _resolved_klass_index = rk; + } + int name_index() const { + return _name_index; + } + int resolved_klass_index() const { + return _resolved_klass_index; + } +}; + class KlassSizeStats; class ConstantPool : public Metadata { @@ -81,7 +97,7 @@ enum { _has_preresolution = 1, // Flags _on_stack = 2, - _is_shared_quick = 4 + _is_shared = 4 }; enum { _invalid_resolved_klass_index = 0xffff @@ -162,7 +178,7 @@ bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } void set_has_preresolution() { - assert(!is_shared_quick(), "should never be called on shared ConstantPools"); + assert(!is_shared(), "should never be called on shared ConstantPools"); _flags |= _has_preresolution; } @@ -174,8 +190,7 @@ void set_on_stack(const bool value); // Faster than MetaspaceObj::is_shared() - used by set_on_stack() - bool is_shared_quick() const { return (_flags & _is_shared_quick) != 0; } - void set_is_shared_quick() { _flags |= _is_shared_quick; } + bool is_shared() const { return (_flags & _is_shared) != 0; } // Klass holding pool InstanceKlass* pool_holder() const { return _pool_holder; } @@ -354,19 +369,28 @@ 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; + 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. - int value = *int_at_addr(which); - int resolved_klass_index = extract_low_short_from_int(value); - int name_index = extract_high_short_from_int(value); - assert(tag_at(name_index).is_symbol(), "sanity"); + CPKlassSlot kslot = klass_slot_at(which); + assert(tag_at(kslot.name_index()).is_symbol(), "sanity"); - Klass** adr = resolved_klasses()->adr_at(resolved_klass_index); + Klass** adr = resolved_klasses()->adr_at(kslot.resolved_klass_index()); return (Klass*)OrderAccess::load_ptr_acquire(adr); } --- old/test/runtime/SharedArchiveFile/LimitSharedSizes.java 2017-04-13 01:30:00.927227635 -0700 +++ new/test/runtime/SharedArchiveFile/LimitSharedSizes.java 2017-04-13 01:30:00.743220685 -0700 @@ -127,7 +127,7 @@ // test with sizes which just meet the minimum required sizes // the following tests also attempt to use the shared archive - new SharedSizeTestData(Region.RO, Platform.is64bit() ? "10M":"9M", Result.VALID_ARCHIVE), + new SharedSizeTestData(Region.RO, Platform.is64bit() ? "14M":"9M", Result.VALID_ARCHIVE), new SharedSizeTestData(Region.RW, Platform.is64bit() ? "12M":"7M", Result.VALID_ARCHIVE), new SharedSizeTestData(Region.MD, Platform.is64bit() ? "4M":"2M", Result.VALID_ARCHIVE), new SharedSizeTestData(Region.MC, "120k", Result.VALID_ARCHIVE),