--- old/src/hotspot/share/classfile/compactHashtable.inline.hpp 2018-08-01 22:33:55.959696381 -0700 +++ new/src/hotspot/share/classfile/compactHashtable.inline.hpp 2018-08-01 22:33:55.631683907 -0700 @@ -28,7 +28,8 @@ #include "classfile/compactHashtable.hpp" #include "classfile/javaClasses.hpp" #include "memory/allocation.inline.hpp" -#include "oops/compressedOops.inline.hpp" +#include "memory/filemap.hpp" +#include "memory/heapShared.inline.hpp" #include "oops/oop.hpp" template @@ -46,8 +47,8 @@ template inline oop CompactHashtable::decode_entry(CompactHashtable* const t, u4 offset, const char* name, int len) { - narrowOop obj = (narrowOop)offset; - oop string = CompressedOops::decode(obj); + narrowOop v = (narrowOop)offset; + oop string = HeapShared::decode_not_null(v); if (java_lang_String::equals(string, (jchar*)name, len)) { return string; } --- old/src/hotspot/share/classfile/javaClasses.cpp 2018-08-01 22:33:56.991735631 -0700 +++ new/src/hotspot/share/classfile/javaClasses.cpp 2018-08-01 22:33:56.655722852 -0700 @@ -1212,7 +1212,7 @@ bool java_lang_Class::restore_archived_mirror(Klass *k, Handle class_loader, Handle module, Handle protection_domain, TRAPS) { - oop m = MetaspaceShared::materialize_archived_object(k->archived_java_mirror_raw()); + oop m = MetaspaceShared::materialize_archived_object(k->archived_java_mirror_raw_narrow()); if (m == NULL) { return false; --- old/src/hotspot/share/gc/g1/heapRegion.cpp 2018-08-01 22:33:58.039775489 -0700 +++ new/src/hotspot/share/gc/g1/heapRegion.cpp 2018-08-01 22:33:57.699762558 -0700 @@ -66,6 +66,13 @@ size_t average_heap_size = (initial_heap_size + max_heap_size) / 2; region_size = MAX2(average_heap_size / HeapRegionBounds::target_number(), HeapRegionBounds::min_size()); + if (DumpSharedSpaces && max_heap_size >= 128*M && region_size < 8*M) { + // CDS archived heap supports up to 32G heaps, with region size up to 8MB. + // At CDS dump time, if we use small regions for G1, the CARC and OARC regions may end up + // in the same 8MB block. At run time with a large heap, G1CollectedHeap::alloc_archive_regions + // might fail because CARC and OARC will end up in the same G1 region. + region_size = 8*M; + } } int region_size_log = log2_long((jlong) region_size); --- old/src/hotspot/share/memory/filemap.cpp 2018-08-01 22:33:59.611835276 -0700 +++ new/src/hotspot/share/memory/filemap.cpp 2018-08-01 22:33:58.719801351 -0700 @@ -35,12 +35,15 @@ #include "logging/logStream.hpp" #include "logging/logMessage.hpp" #include "memory/filemap.hpp" +#include "memory/heapShared.inline.hpp" +#include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/objArrayOop.hpp" +#include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/arguments.hpp" #include "runtime/java.hpp" @@ -188,6 +191,9 @@ _shared_path_table_size = mapinfo->_shared_path_table_size; _shared_path_table = mapinfo->_shared_path_table; _shared_path_entry_size = mapinfo->_shared_path_entry_size; + if (MetaspaceShared::is_heap_object_archiving_allowed()) { + _g1_reserved = G1CollectedHeap::heap()->g1_reserved(); + } // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's @@ -525,7 +531,7 @@ } size_t len = lseek(fd, 0, SEEK_END); - struct FileMapInfo::FileMapHeader::space_info* si = + FileMapHeader::space_info* si = &_header->_space[MetaspaceShared::last_valid_region]; // The last space might be empty if (si->_file_offset > len || len - si->_file_offset < si->_used) { @@ -607,7 +613,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size, bool read_only, bool allow_exec) { - struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region]; + FileMapHeader::space_info* si = &_header->_space[region]; if (_file_open) { guarantee(si->_file_offset == _file_offset, "file offset mismatch."); @@ -760,7 +766,7 @@ // Remap the shared readonly space to shared readwrite, private. bool FileMapInfo::remap_shared_readonly_as_readwrite() { int idx = MetaspaceShared::ro; - struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[idx]; + FileMapHeader::space_info* si = &_header->_space[idx]; if (!si->_read_only) { // the space is already readwrite so we are done return true; @@ -812,7 +818,7 @@ char* FileMapInfo::map_region(int i, char** top_ret) { assert(!MetaspaceShared::is_heap_region(i), "sanity"); - struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; + FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t alignment = os::vm_allocation_granularity(); size_t size = align_up(used, alignment); @@ -852,6 +858,10 @@ static int num_open_archive_heap_ranges = 0; #if INCLUDE_CDS_JAVA_HEAP +bool FileMapInfo::has_heap_regions() { + return (_header->_space[MetaspaceShared::first_string]._used > 0); +} + // // Map the shared string objects and open archive heap objects to the runtime // java heap. @@ -866,55 +876,79 @@ // During runtime execution, out-going references to any other java heap // regions may be added. GC may mark and update references in the mapped // open archive objects. -void FileMapInfo::map_heap_regions() { - if (MetaspaceShared::is_heap_object_archiving_allowed()) { - log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", - narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift()); - log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", - p2i(narrow_klass_base()), narrow_klass_shift()); - - // Check that all the narrow oop and klass encodings match the archive - if (narrow_oop_mode() != Universe::narrow_oop_mode() || - narrow_oop_base() != Universe::narrow_oop_base() || - narrow_oop_shift() != Universe::narrow_oop_shift() || - narrow_klass_base() != Universe::narrow_klass_base() || - narrow_klass_shift() != Universe::narrow_klass_shift()) { - if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) { - log_info(cds)("Cached heap data from the CDS archive is being ignored. " - "The current CompressedOops/CompressedClassPointers encoding differs from " - "that archived due to heap size change. The archive was dumped using max heap " - "size " UINTX_FORMAT "M.", max_heap_size()/M); - log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", - Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()), - Universe::narrow_oop_shift()); - log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", - p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift()); - } - } else { - // First, map string regions as closed archive heap regions. - // GC does not write into the regions. - if (map_heap_data(&string_ranges, - MetaspaceShared::first_string, - MetaspaceShared::max_strings, - &num_string_ranges)) { - StringTable::set_shared_string_mapped(); - - // Now, map open_archive heap regions, GC can write into the regions. - if (map_heap_data(&open_archive_heap_ranges, - MetaspaceShared::first_open_archive_heap_region, - MetaspaceShared::max_open_archive_heap_region, - &num_open_archive_heap_ranges, - true /* open */)) { - MetaspaceShared::set_open_archive_heap_region_mapped(); - } - } - } - } else { - if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) { - log_info(cds)("Cached heap data from the CDS archive is being ignored. UseG1GC, " - "UseCompressedOops and UseCompressedClassPointers are required."); +void FileMapInfo::map_heap_regions_impl() { + if (!MetaspaceShared::is_heap_object_archiving_allowed()) { + log_info(cds)("Cached heap data from the CDS archive is being ignored. UseG1GC, " + "UseCompressedOops and UseCompressedClassPointers are required."); + return; + } + + if (narrow_klass_base() != Universe::narrow_klass_base() || + narrow_klass_shift() != Universe::narrow_klass_shift()) { + log_info(cds)("Cached heap data from the CDS archive need to be relocated because"); + log_info(cds)("the CDS archive was created with an incompatible heap size: " UINTX_FORMAT "M.", max_heap_size()/M); + log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", + p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift()); + return; + } + + log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", + narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift()); + log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", + p2i(narrow_klass_base()), narrow_klass_shift()); + + ptrdiff_t delta = 0; + + if (narrow_oop_mode() != Universe::narrow_oop_mode() || + narrow_oop_base() != Universe::narrow_oop_base() || + narrow_oop_shift() != Universe::narrow_oop_shift()) { + log_info(cds)("Cached heap data from the CDS archive need to be relocated because"); + log_info(cds)("the CDS archive was created with an incompatible heap size: " UINTX_FORMAT "M.", max_heap_size()/M); + log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", + Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()), + Universe::narrow_oop_shift()); + + _heap_pointers_need_relocation = true; + + // dumptime heap end ------------v + // [ |archived heap regions| ] runtime heap end ------v + // [ |archived heap regions| ] + // |<-----delta-------------------->| + // + // At dump time, the archived heap region were near the top of the heap. + // At run time, that region may not be inside the heap, so we move it so + // that it's now near the top of teh runtime time. This can be done by + // the simple math of adding the delta as shown above. + address dumptime_heap_end = (address)_header->_g1_reserved.end(); + address runtime_heap_end = (address)G1CollectedHeap::heap()->g1_reserved().end(); + delta = runtime_heap_end - dumptime_heap_end; + } + + HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift()); + + // First, map string regions as closed archive heap regions. + // GC does not write into the regions. + if (map_heap_data(&string_ranges, + MetaspaceShared::first_string, + MetaspaceShared::max_strings, + &num_string_ranges)) { + StringTable::set_shared_string_mapped(); + + // Now, map open_archive heap regions, GC can write into the regions. + if (map_heap_data(&open_archive_heap_ranges, + MetaspaceShared::first_open_archive_heap_region, + MetaspaceShared::max_open_archive_heap_region, + &num_open_archive_heap_ranges, + true /* open */)) { + MetaspaceShared::set_open_archive_heap_region_mapped(); } } +} + +void FileMapInfo::map_heap_regions() { + if (has_heap_regions()) { + map_heap_regions_impl(); + } if (!StringTable::shared_string_mapped()) { assert(string_ranges == NULL && num_string_ranges == 0, "sanity"); @@ -928,16 +962,15 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first, int max, int* num, bool is_open_archive) { MemRegion * regions = new MemRegion[max]; - struct FileMapInfo::FileMapHeader::space_info* si; + FileMapHeader::space_info* si; int region_num = 0; for (int i = first; i < first + max; i++) { si = &_header->_space[i]; - size_t used = si->_used; - if (used > 0) { - size_t size = used; - char* requested_addr = (char*)((void*)CompressedOops::decode_not_null( + size_t size = si->_used; + if (size > 0) { + char* requested_addr = (char*)((void*)HeapShared::decode_not_null( (narrowOop)si->_addr._offset)); regions[region_num] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize); region_num ++; @@ -1003,6 +1036,51 @@ return true; } +void FileMapInfo::relocate_archived_heap_embedded_pointers() { + if (!_heap_pointers_need_relocation) { + return; + } + + relocate_archived_heap_embedded_pointers_impl(string_ranges, + num_string_ranges); + + relocate_archived_heap_embedded_pointers_impl(open_archive_heap_ranges, + num_open_archive_heap_ranges); +} + +class RelocateInternalPointers: public BasicOopIterateClosure { + public: + virtual bool should_verify_oops(void) { + return false; + } + virtual void do_oop(narrowOop *p) { + narrowOop v = *p; + if (!CompressedOops::is_null(v)) { + oop o = HeapShared::decode_not_null(v); + RawAccess::oop_store(p, o); + } + } + virtual void do_oop(oop *p) { + ShouldNotReachHere(); + } +}; + +void FileMapInfo::relocate_archived_heap_embedded_pointers_impl(MemRegion *heap_mem, int num) { + RelocateInternalPointers relocator; + + for (int i=0; ioop_iterate(&relocator); + p += o->size(); + } + } +} + +// This internally allocates objects using SystemDictionary::Object_klass(), so it +// must be called after the well-known classes are resolved. void FileMapInfo::fixup_mapped_heap_regions() { // If any string regions were found, call the fill routine to make them parseable. // Note that string_ranges may be non-NULL even if no ranges were found. @@ -1057,7 +1135,7 @@ void FileMapInfo::unmap_region(int i) { assert(!MetaspaceShared::is_heap_region(i), "sanity"); - struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; + FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t size = align_up(used, os::vm_allocation_granularity()); @@ -1086,6 +1164,7 @@ FileMapInfo* FileMapInfo::_current_info = NULL; +bool FileMapInfo::_heap_pointers_need_relocation = false; Array* FileMapInfo::_shared_path_table = NULL; int FileMapInfo::_shared_path_table_size = 0; size_t FileMapInfo::_shared_path_entry_size = 0x1234baad; --- old/src/hotspot/share/memory/filemap.hpp 2018-08-01 22:34:00.859882741 -0700 +++ new/src/hotspot/share/memory/filemap.hpp 2018-08-01 22:34:00.507869354 -0700 @@ -144,6 +144,7 @@ size_t _cds_i2i_entry_code_buffers_size; size_t _core_spaces_size; // number of bytes allocated by the core spaces // (mc, md, ro, rw and od). + MemRegion _g1_reserved; // reserved region at dump time. struct space_info { int _crc; // crc checksum of the current space size_t _file_offset; // sizeof(this) rounded to vm page size @@ -214,6 +215,7 @@ char* _paths_misc_info; static FileMapInfo* _current_info; + static bool _heap_pointers_need_relocation; bool init_from_file(int fd); void align_file_position(); @@ -278,8 +280,12 @@ void write_bytes(const void* buffer, int count); void write_bytes_aligned(const void* buffer, int count); char* map_region(int i, char** top_ret); + void map_heap_regions_impl() NOT_CDS_JAVA_HEAP_RETURN; void map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; + void relocate_archived_heap_embedded_pointers() NOT_CDS_JAVA_HEAP_RETURN; + void relocate_archived_heap_embedded_pointers_impl(MemRegion *heap_mem, int num) NOT_CDS_JAVA_HEAP_RETURN; + bool has_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; void unmap_region(int i); bool verify_region_checksum(int i); void close(); --- old/src/hotspot/share/memory/heapShared.cpp 2018-08-01 22:34:02.591948615 -0700 +++ new/src/hotspot/share/memory/heapShared.cpp 2018-08-01 22:34:01.607911190 -0700 @@ -28,7 +28,7 @@ #include "logging/log.hpp" #include "logging/logMessage.hpp" #include "logging/logStream.hpp" -#include "memory/heapShared.hpp" +#include "memory/heapShared.inline.hpp" #include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" @@ -70,6 +70,9 @@ return info; } +address HeapShared::_narrow_oop_base; +int HeapShared::_narrow_oop_shift; + int HeapShared::num_of_subgraph_infos() { int num = 0; KlassSubGraphInfo* info = _subgraph_info_list; @@ -311,7 +314,7 @@ // point. All objects in the subgraph reachable from the object are // also 'known' by GC. oop v = MetaspaceShared::materialize_archived_object( - CompressedOops::decode(entry_field_records->at(i+1))); + entry_field_records->at(i+1)); m->obj_field_put(field_offset, v); i += 2; } @@ -503,4 +506,10 @@ void HeapShared::archive_module_graph_objects(Thread* THREAD) { do_module_object_graph(archive_reachable_objects_from_static_field); } + +void HeapShared::init_narrow_oop_decoding(address base, int shift) { + _narrow_oop_base = base; + _narrow_oop_shift = shift; +} + #endif // INCLUDE_CDS_JAVA_HEAP --- old/src/hotspot/share/memory/heapShared.hpp 2018-08-01 22:34:03.515983757 -0700 +++ new/src/hotspot/share/memory/heapShared.hpp 2018-08-01 22:34:03.171970673 -0700 @@ -123,12 +123,22 @@ static int num_of_subgraph_infos(); static size_t build_archived_subgraph_info_records(int num_records); + + // Used by decode_not_null + static address _narrow_oop_base; + static int _narrow_oop_shift; + #endif // INCLUDE_CDS_JAVA_HEAP public: static char* read_archived_subgraph_infos(char* buffer) NOT_CDS_JAVA_HEAP_RETURN_(buffer); static void write_archived_subgraph_infos() NOT_CDS_JAVA_HEAP_RETURN; static void initialize_from_archived_subgraph(Klass* k) NOT_CDS_JAVA_HEAP_RETURN; + // When reading an (unrelocated) narrowOop from the archive, use this function + // instead of CompressedOops::decode_not_null + inline static oop decode_not_null(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN; + static void archive_module_graph_objects(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN; }; #endif // SHARE_VM_MEMORY_HEAPSHARED_HPP --- old/src/hotspot/share/memory/metaspaceShared.cpp 2018-08-01 22:34:04.420018139 -0700 +++ new/src/hotspot/share/memory/metaspaceShared.cpp 2018-08-01 22:34:04.088005513 -0700 @@ -39,7 +39,7 @@ #include "logging/log.hpp" #include "logging/logMessage.hpp" #include "memory/filemap.hpp" -#include "memory/heapShared.hpp" +#include "memory/heapShared.inline.hpp" #include "memory/metaspace.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" @@ -309,10 +309,10 @@ Universe::set_narrow_klass_range(cds_total); Metaspace::initialize_class_space(tmp_class_space); - tty->print_cr("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", + log_info(cds)("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift()); - tty->print_cr("Allocated temporary class space: " SIZE_FORMAT " bytes at " PTR_FORMAT, + log_info(cds)("Allocated temporary class space: " SIZE_FORMAT " bytes at " PTR_FORMAT, CompressedClassSpaceSize, p2i(tmp_class_space.base())); #endif @@ -462,6 +462,7 @@ java_lang_LiveStackFrameInfo::serialize(soc); java_util_concurrent_locks_AbstractOwnableSynchronizer::serialize(soc); jdk_internal_module_ArchivedModuleGraph::serialize(soc); + InstanceMirrorKlass::serialize(soc); } address MetaspaceShared::cds_i2i_entry_code_buffers(size_t total_size) { @@ -1924,8 +1925,9 @@ return archived_oop; } -oop MetaspaceShared::materialize_archived_object(oop obj) { - if (obj != NULL) { +oop MetaspaceShared::materialize_archived_object(narrowOop v) { + if (!CompressedOops::is_null(v)) { + oop obj = HeapShared::decode_not_null(v); return G1CollectedHeap::heap()->materialize_archived_object(obj); } return NULL; @@ -2001,7 +2003,7 @@ "Archived heap object is not allowed"); assert(MetaspaceShared::open_archive_heap_region_mapped(), "Open archive heap region is not mapped"); - *p = CompressedOops::decode_not_null(o); + *p = HeapShared::decode_not_null(o); } } @@ -2148,6 +2150,8 @@ // Initialize the run-time symbol table. SymbolTable::create_table(); + mapinfo->relocate_archived_heap_embedded_pointers(); + // Close the mapinfo file mapinfo->close(); --- old/src/hotspot/share/memory/metaspaceShared.hpp 2018-08-01 22:34:05.804070777 -0700 +++ new/src/hotspot/share/memory/metaspaceShared.hpp 2018-08-01 22:34:05.464057846 -0700 @@ -111,7 +111,7 @@ } static oop find_archived_heap_object(oop obj); static oop archive_heap_object(oop obj, Thread* THREAD); - static oop materialize_archived_object(oop obj); + static oop materialize_archived_object(narrowOop v); static void archive_klass_objects(Thread* THREAD); #endif --- old/src/hotspot/share/memory/universe.cpp 2018-08-01 22:34:07.616139693 -0700 +++ new/src/hotspot/share/memory/universe.cpp 2018-08-01 22:34:06.616101660 -0700 @@ -513,8 +513,11 @@ // that the number of objects allocated at this point is very small. assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded"); HandleMark hm(THREAD); - // Cache the start of the static fields - InstanceMirrorKlass::init_offset_of_static_fields(); + + if (!UseSharedSpaces) { + // Cache the start of the static fields + InstanceMirrorKlass::init_offset_of_static_fields(); + } GrowableArray * list = java_lang_Class::fixup_mirror_list(); int list_length = list->length(); --- old/src/hotspot/share/oops/cpCache.cpp 2018-08-01 22:34:09.232201156 -0700 +++ new/src/hotspot/share/oops/cpCache.cpp 2018-08-01 22:34:08.416170120 -0700 @@ -778,7 +778,7 @@ if (CompressedOops::is_null(_archived_references)) { return NULL; } - return MetaspaceShared::materialize_archived_object(CompressedOops::decode_not_null(_archived_references)); + return MetaspaceShared::materialize_archived_object(_archived_references); } void ConstantPoolCache::set_archived_references(oop o) { --- old/src/hotspot/share/oops/instanceMirrorKlass.cpp 2018-08-01 22:34:10.420246340 -0700 +++ new/src/hotspot/share/oops/instanceMirrorKlass.cpp 2018-08-01 22:34:10.084233561 -0700 @@ -66,3 +66,9 @@ } return 0; } + +#if INCLUDE_CDS +void InstanceMirrorKlass::serialize(SerializeClosure* f) { + f->do_u4((u4*)&_offset_of_static_fields); +} +#endif --- old/src/hotspot/share/oops/instanceMirrorKlass.hpp 2018-08-01 22:34:11.824299739 -0700 +++ new/src/hotspot/share/oops/instanceMirrorKlass.hpp 2018-08-01 22:34:11.088271746 -0700 @@ -99,6 +99,8 @@ void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); #endif + static void serialize(class SerializeClosure* f) NOT_CDS_RETURN; + // Oop fields (and metadata) iterators // // The InstanceMirrorKlass iterators also visit the hidden Klass pointer. --- old/src/hotspot/share/oops/klass.cpp 2018-08-01 22:34:13.084347662 -0700 +++ new/src/hotspot/share/oops/klass.cpp 2018-08-01 22:34:12.748334883 -0700 @@ -571,6 +571,11 @@ return CompressedOops::decode(_archived_mirror); } +narrowOop Klass::archived_java_mirror_raw_narrow() { + assert(has_raw_archived_mirror(), "must have raw archived mirror"); + return _archived_mirror; +} + // No GC barrier void Klass::set_archived_java_mirror_raw(oop m) { assert(DumpSharedSpaces, "called only during runtime"); --- old/src/hotspot/share/oops/klass.hpp 2018-08-01 22:34:14.628406386 -0700 +++ new/src/hotspot/share/oops/klass.hpp 2018-08-01 22:34:13.880377937 -0700 @@ -261,6 +261,7 @@ void set_java_mirror(Handle m); oop archived_java_mirror_raw() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // no GC barrier + narrowOop archived_java_mirror_raw_narrow() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // no GC barrier void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier // Temporary mirror switch used by RedefineClasses --- /dev/null 2017-05-05 06:40:48.273288351 -0700 +++ new/src/hotspot/share/memory/heapShared.inline.hpp 2018-08-01 22:34:15.352433923 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP +#define SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP + +#include "oops/compressedOops.inline.hpp" +#include "memory/heapShared.hpp" + +#if INCLUDE_CDS_JAVA_HEAP + +inline oop HeapShared::decode_not_null(narrowOop v) { + assert(!CompressedOops::is_null(v), "narrow oop value can never be zero"); + oop result = (oop)(void*)((uintptr_t)_narrow_oop_base + ((uintptr_t)v << _narrow_oop_shift)); + assert(check_obj_alignment(result), "address not aligned: " INTPTR_FORMAT, p2i((void*) result)); + return result; +} + +#endif + +#endif // SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP --- /dev/null 2017-05-05 06:40:48.273288351 -0700 +++ new/test/hotspot/jtreg/runtime/appcds/cacheObject/DifferentHeapSizes.java 2018-08-01 22:34:16.868491583 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @summary Test automatic relocation of archive heap regions dur to heap size changes. + * @requires vm.cds.archived.java.heap + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.jartool/sun.tools.jar + * @compile ../test-classes/Hello.java + * @run main DifferentHeapSizes + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class DifferentHeapSizes { + static class Scenario { + int dumpSize; // in MB + int runSizes[]; // in MB + Scenario(int ds, int... rs) { + dumpSize = ds; + runSizes = rs; + } + } + + static Scenario[] scenarios = { + // dump -Xmx , run -Xmx + new Scenario( 128, 32, 64, 512, 2048, 4097, 16374, 31000), + new Scenario( 2048, 32, 512, 2600, 4097, 8500, 31000), + new Scenario( 17000, 32, 512, 2048, 4097, 8500, 31000), + new Scenario( 31000, 32, 512, 2048, 4097, 8500, 17000) + }; + + public static void main(String[] args) throws Exception { + JarBuilder.getOrCreateHelloJar(); + String appJar = TestCommon.getTestJar("hello.jar"); + String appClasses[] = TestCommon.list("Hello"); + + for (Scenario s : scenarios) { + String dumpXmx = "-Xmx" + s.dumpSize + "m"; + OutputAnalyzer output = TestCommon.dump(appJar, appClasses, dumpXmx); + + for (int runSize : s.runSizes) { + String runXmx = "-Xmx" + runSize + "m"; + TestCommon.run("-cp", appJar, "-showversion", "-Xlog:cds", runXmx, "Hello") + .assertNormalExit("Hello World") + .assertNormalExit(out -> { + out.shouldNotContain("Unable to allocate region, range is not within java heap."); + out.shouldNotContain("Unable to allocate region, java heap range is already in use."); + }); + } + } + } +}