--- old/src/hotspot/share/classfile/javaClasses.cpp 2018-06-11 16:16:15.346087935 -0400 +++ new/src/hotspot/share/classfile/javaClasses.cpp 2018-06-11 16:16:15.074073808 -0400 @@ -63,7 +63,6 @@ #include "runtime/vframe.inline.hpp" #include "utilities/align.hpp" #include "utilities/preserveException.hpp" - #if INCLUDE_JVMCI #include "jvmci/jvmciJavaClasses.hpp" #endif @@ -798,7 +797,7 @@ // During bootstrap, java.lang.Class wasn't loaded so static field // offsets were computed without the size added it. Go back and // update all the static field offsets to included the size. - for (JavaFieldStream fs(InstanceKlass::cast(k)); !fs.done(); fs.next()) { + for (JavaFieldStream fs(InstanceKlass::cast(k)); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { int real_offset = fs.offset() + InstanceMirrorKlass::offset_of_static_fields(); fs.set_offset(real_offset); @@ -809,12 +808,8 @@ if (k->is_shared() && k->has_raw_archived_mirror()) { if (MetaspaceShared::open_archive_heap_region_mapped()) { - oop m = k->archived_java_mirror(); - assert(m != NULL, "archived mirror is NULL"); - assert(MetaspaceShared::is_archive_object(m), "must be archived mirror object"); - Handle m_h(THREAD, m); - // restore_archived_mirror() clears the klass' _has_raw_archived_mirror flag - restore_archived_mirror(k, m_h, Handle(), Handle(), Handle(), CHECK); + bool present = restore_archived_mirror(k, Handle(), Handle(), Handle(), CHECK); + assert(present, "Missing archived mirror for %s", k->external_name()); return; } else { k->set_java_mirror_handle(NULL); @@ -1207,11 +1202,23 @@ return archived_mirror; } -// After the archived mirror object is restored, the shared klass' -// _has_raw_archived_mirror flag is cleared -void java_lang_Class::restore_archived_mirror(Klass *k, Handle mirror, +// Returns true if the mirror is updated, false if no archived mirror +// data is present. After the archived mirror object is restored, the +// shared klass' _has_raw_archived_mirror flag is cleared. +bool java_lang_Class::restore_archived_mirror(Klass *k, Handle class_loader, Handle module, Handle protection_domain, TRAPS) { + oop m = MetaspaceShared::unarchive_heap_object(k->archived_java_mirror_raw()); + + if (m == NULL) { + return false; + } + + log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m)); + + // mirror is archived, restore + assert(MetaspaceShared::is_archive_object(m), "must be archived mirror object"); + Handle mirror(THREAD, m); // The java.lang.Class field offsets were archived and reloaded from archive. // No need to put classes on the fixup_mirror_list before java.lang.Class @@ -1221,7 +1228,7 @@ // - local static final fields with initial values were initialized at dump time // create the init_lock - typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK); + typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_(false)); set_init_lock(mirror(), r); if (protection_domain.not_null()) { @@ -1241,6 +1248,8 @@ ResourceMark rm; log_trace(cds, mirror)("Restored %s archived mirror " PTR_FORMAT, k->external_name(), p2i(mirror())); + + return true; } #endif // INCLUDE_CDS_JAVA_HEAP --- old/src/hotspot/share/classfile/javaClasses.hpp 2018-06-11 16:16:16.242134502 -0400 +++ new/src/hotspot/share/classfile/javaClasses.hpp 2018-06-11 16:16:15.930118282 -0400 @@ -229,8 +229,9 @@ static oop archive_mirror(Klass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(NULL); static oop process_archived_mirror(Klass* k, oop mirror, oop archived_mirror, Thread *THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL); - static void restore_archived_mirror(Klass *k, Handle mirror, Handle class_loader, Handle module, - Handle protection_domain, TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + static bool restore_archived_mirror(Klass *k, Handle class_loader, Handle module, + Handle protection_domain, + TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(false); static void fixup_module_field(Klass* k, Handle module); --- old/src/hotspot/share/gc/g1/g1BarrierSet.hpp 2018-06-11 16:16:17.142181267 -0400 +++ new/src/hotspot/share/gc/g1/g1BarrierSet.hpp 2018-06-11 16:16:16.830165060 -0400 @@ -50,7 +50,7 @@ // pre-marking object graph. static void enqueue(oop pre_val); - static void enqueue_if_weak_or_archive(DecoratorSet decorators, oop value); + static void enqueue_if_weak(DecoratorSet decorators, oop value); template void write_ref_array_pre_work(T* dst, size_t count); virtual void write_ref_array_pre(oop* dst, size_t count, bool dest_uninitialized); --- old/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp 2018-06-11 16:16:18.022227015 -0400 +++ new/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp 2018-06-11 16:16:17.710210790 -0400 @@ -54,15 +54,14 @@ } } -inline void G1BarrierSet::enqueue_if_weak_or_archive(DecoratorSet decorators, oop value) { +inline void G1BarrierSet::enqueue_if_weak(DecoratorSet decorators, oop value) { assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); - // Archive roots need to be enqueued since they add subgraphs to the - // Java heap that were not there at the snapshot when marking started. - // Weak and phantom references also need enqueueing for similar reasons. - const bool in_archive_root = (decorators & IN_ARCHIVE_ROOT) != 0; + // Loading from a weak or phantom reference needs enqueueing, as + // the object may not have been reachable (part of the snapshot) + // when marking started. const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0; const bool peek = (decorators & AS_NO_KEEPALIVE) != 0; - const bool needs_enqueue = in_archive_root || (!peek && !on_strong_oop_ref); + const bool needs_enqueue = (!peek && !on_strong_oop_ref); if (needs_enqueue && value != NULL) { enqueue(value); @@ -74,7 +73,7 @@ inline oop G1BarrierSet::AccessBarrier:: oop_load_not_in_heap(T* addr) { oop value = ModRef::oop_load_not_in_heap(addr); - enqueue_if_weak_or_archive(decorators, value); + enqueue_if_weak(decorators, value); return value; } @@ -83,7 +82,7 @@ inline oop G1BarrierSet::AccessBarrier:: oop_load_in_heap(T* addr) { oop value = ModRef::oop_load_in_heap(addr); - enqueue_if_weak_or_archive(decorators, value); + enqueue_if_weak(decorators, value); return value; } @@ -91,7 +90,7 @@ inline oop G1BarrierSet::AccessBarrier:: oop_load_in_heap_at(oop base, ptrdiff_t offset) { oop value = ModRef::oop_load_in_heap_at(base, offset); - enqueue_if_weak_or_archive(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset), value); + enqueue_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset), value); return value; } --- old/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-06-11 16:16:18.894272333 -0400 +++ new/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-06-11 16:16:18.582256111 -0400 @@ -78,6 +78,7 @@ #include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/iterator.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" @@ -823,6 +824,18 @@ decrease_used(size_used); } +oop G1CollectedHeap::materialize_archived_object(oop obj) { + assert(obj != NULL, "archived obj is NULL"); + assert(MetaspaceShared::is_archive_object(obj), "must be archived object"); + + // Loading an archived object makes it strongly reachable. If it is + // loaded during concurrent marking, it must be enqueued to the SATB + // queue, shading the previously white object gray. + G1BarrierSet::enqueue(obj); + + return obj; +} + HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { ResourceMark rm; // For retrieving the thread names in log messages. --- old/src/hotspot/share/gc/g1/g1CollectedHeap.hpp 2018-06-11 16:16:19.834321179 -0400 +++ new/src/hotspot/share/gc/g1/g1CollectedHeap.hpp 2018-06-11 16:16:19.522304960 -0400 @@ -699,6 +699,8 @@ // mapping failed, with the same non-overlapping and sorted MemRegion array. void dealloc_archive_regions(MemRegion* range, size_t count); + oop materialize_archived_object(oop obj); + private: // Shrink the garbage-first heap by at most the given size (in bytes!). --- old/src/hotspot/share/memory/metaspaceShared.cpp 2018-06-11 16:16:20.730367742 -0400 +++ new/src/hotspot/share/memory/metaspaceShared.cpp 2018-06-11 16:16:20.410351117 -0400 @@ -1910,6 +1910,11 @@ return archived_oop; } +oop MetaspaceShared::unarchive_heap_object(oop obj) { + assert(obj != NULL, "sanity"); + return G1CollectedHeap::heap()->materialize_archived_object(obj); +} + void MetaspaceShared::archive_klass_objects(Thread* THREAD) { int i; for (i = 0; i < _global_klass_objects->length(); i++) { @@ -1980,7 +1985,7 @@ "Archived heap object is not allowed"); assert(MetaspaceShared::open_archive_heap_region_mapped(), "Open archive heap region is not mapped"); - RootAccess::oop_store(p, CompressedOops::decode_not_null(o)); + *p = CompressedOops::decode_not_null(o); } } --- old/src/hotspot/share/memory/metaspaceShared.hpp 2018-06-11 16:16:21.642415146 -0400 +++ new/src/hotspot/share/memory/metaspaceShared.hpp 2018-06-11 16:16:21.330398921 -0400 @@ -111,6 +111,7 @@ } static oop find_archived_heap_object(oop obj); static oop archive_heap_object(oop obj, Thread* THREAD); + static oop unarchive_heap_object(oop obj); static void archive_klass_objects(Thread* THREAD); #endif --- old/src/hotspot/share/oops/access.hpp 2018-06-11 16:16:22.510460248 -0400 +++ new/src/hotspot/share/oops/access.hpp 2018-06-11 16:16:22.198444027 -0400 @@ -379,8 +379,7 @@ (location_decorators ^ IN_ROOT) == 0 || (location_decorators ^ IN_HEAP) == 0 || (location_decorators ^ (IN_HEAP | IN_HEAP_ARRAY)) == 0 || - (location_decorators ^ (IN_ROOT | IN_CONCURRENT_ROOT)) == 0 || - (location_decorators ^ (IN_ROOT | IN_ARCHIVE_ROOT)) == 0 + (location_decorators ^ (IN_ROOT | IN_CONCURRENT_ROOT)) == 0 )); } --- old/src/hotspot/share/oops/accessDecorators.hpp 2018-06-11 16:16:23.386505771 -0400 +++ new/src/hotspot/share/oops/accessDecorators.hpp 2018-06-11 16:16:23.074489556 -0400 @@ -192,10 +192,8 @@ const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 21; const DecoratorSet IN_ROOT = UCONST64(1) << 22; const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 23; -const DecoratorSet IN_ARCHIVE_ROOT = UCONST64(1) << 24; const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_HEAP_ARRAY | - IN_ROOT | IN_CONCURRENT_ROOT | - IN_ARCHIVE_ROOT; + IN_ROOT | IN_CONCURRENT_ROOT; // == Value Decorators == // * OOP_NOT_NULL: This property can make certain barriers faster such as compressing oops. @@ -245,9 +243,7 @@ ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY); static const DecoratorSet conc_root_is_root = heap_array_is_in_heap | ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY); - static const DecoratorSet archive_root_is_root = conc_root_is_root | - ((IN_ARCHIVE_ROOT & conc_root_is_root) != 0 ? IN_ROOT : INTERNAL_EMPTY); - static const DecoratorSet value = archive_root_is_root | BT_BUILDTIME_DECORATORS; + static const DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS; }; // This function implements the above DecoratorFixup rules, but without meta @@ -268,9 +264,7 @@ ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY); DecoratorSet conc_root_is_root = heap_array_is_in_heap | ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY); - DecoratorSet archive_root_is_root = conc_root_is_root | - ((IN_ARCHIVE_ROOT & conc_root_is_root) != 0 ? IN_ROOT : INTERNAL_EMPTY); - DecoratorSet value = archive_root_is_root | BT_BUILDTIME_DECORATORS; + DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS; return value; } } --- old/src/hotspot/share/oops/cpCache.cpp 2018-06-11 16:16:24.258551089 -0400 +++ new/src/hotspot/share/oops/cpCache.cpp 2018-06-11 16:16:23.942534669 -0400 @@ -32,6 +32,7 @@ #include "logging/log.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" @@ -743,16 +744,15 @@ #if INCLUDE_CDS_JAVA_HEAP oop ConstantPoolCache::archived_references() { - // Loading an archive root forces the oop to become strongly reachable. - // For example, if it is loaded during concurrent marking in a SATB - // collector, it will be enqueued to the SATB queue, effectively - // shading the previously white object gray. - return RootAccess::oop_load(&_archived_references); + if (CompressedOops::is_null(_archived_references)) { + return NULL; + } + return MetaspaceShared::unarchive_heap_object(CompressedOops::decode_not_null(_archived_references)); } void ConstantPoolCache::set_archived_references(oop o) { assert(DumpSharedSpaces, "called only during runtime"); - RootAccess::oop_store(&_archived_references, o); + _archived_references = CompressedOops::encode(o); } #endif --- old/src/hotspot/share/oops/klass.cpp 2018-06-11 16:16:25.134596616 -0400 +++ new/src/hotspot/share/oops/klass.cpp 2018-06-11 16:16:24.822580401 -0400 @@ -529,20 +529,19 @@ Handle module_handle(THREAD, ((module_entry != NULL) ? module_entry->module() : (oop)NULL)); if (this->has_raw_archived_mirror()) { + ResourceMark rm; log_debug(cds, mirror)("%s has raw archived mirror", external_name()); if (MetaspaceShared::open_archive_heap_region_mapped()) { - oop m = archived_java_mirror(); - log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m)); - if (m != NULL) { - // mirror is archived, restore - assert(MetaspaceShared::is_archive_object(m), "must be archived mirror object"); - Handle m_h(THREAD, m); - java_lang_Class::restore_archived_mirror(this, m_h, loader, module_handle, protection_domain, CHECK); + bool present = java_lang_Class::restore_archived_mirror(this, loader, module_handle, + protection_domain, + CHECK); + if (present) { return; } } // No archived mirror data + log_debug(cds, mirror)("No archived mirror data for %s", external_name()); _java_mirror = NULL; this->clear_has_raw_archived_mirror(); } @@ -558,18 +557,10 @@ #if INCLUDE_CDS_JAVA_HEAP // Used at CDS dump time to access the archived mirror. No GC barrier. oop Klass::archived_java_mirror_raw() { - assert(DumpSharedSpaces, "called only during runtime"); assert(has_raw_archived_mirror(), "must have raw archived mirror"); return CompressedOops::decode(_archived_mirror); } -// Used at CDS runtime to get the archived mirror from shared class. Uses GC barrier. -oop Klass::archived_java_mirror() { - assert(UseSharedSpaces, "UseSharedSpaces expected."); - assert(has_raw_archived_mirror(), "must have raw archived mirror"); - return RootAccess::oop_load(&_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-06-11 16:16:26.026642975 -0400 +++ new/src/hotspot/share/oops/klass.hpp 2018-06-11 16:16:25.706626341 -0400 @@ -244,7 +244,6 @@ void set_java_mirror(Handle m); oop archived_java_mirror_raw() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // no GC barrier - oop archived_java_mirror() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // accessor with GC barrier void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier // Temporary mirror switch used by RedefineClasses