--- old/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp 2018-01-09 13:49:18.299913506 +0100 +++ new/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp 2018-01-09 13:49:17.995913517 +0100 @@ -54,7 +54,7 @@ // pre-marking object graph. static void enqueue(oop pre_val); - static void enqueue_if_weak(DecoratorSet decorators, oop value); + static void enqueue_if_weak_or_archive(DecoratorSet decorators, oop value); template void write_ref_array_pre_work(T* dst, int count); virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized); --- old/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.inline.hpp 2018-01-09 13:49:19.195913475 +0100 +++ new/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.inline.hpp 2018-01-09 13:49:18.883913486 +0100 @@ -61,12 +61,17 @@ _byte_map[card_index] = val; } -inline void G1SATBCardTableModRefBS::enqueue_if_weak(DecoratorSet decorators, oop value) { +inline void G1SATBCardTableModRefBS::enqueue_if_weak_or_archive(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; 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); - if (!peek && !on_strong_oop_ref && value != NULL) { + if (needs_enqueue && value != NULL) { enqueue(value); } } @@ -76,7 +81,7 @@ inline oop G1SATBCardTableLoggingModRefBS::AccessBarrier:: oop_load_not_in_heap(T* addr) { oop value = ModRef::oop_load_not_in_heap(addr); - enqueue_if_weak(decorators, value); + enqueue_if_weak_or_archive(decorators, value); return value; } @@ -85,7 +90,7 @@ inline oop G1SATBCardTableLoggingModRefBS::AccessBarrier:: oop_load_in_heap(T* addr) { oop value = ModRef::oop_load_in_heap(addr); - enqueue_if_weak(decorators, value); + enqueue_if_weak_or_archive(decorators, value); return value; } @@ -93,7 +98,7 @@ inline oop G1SATBCardTableLoggingModRefBS::AccessBarrier:: oop_load_in_heap_at(oop base, ptrdiff_t offset) { oop value = ModRef::oop_load_in_heap_at(base, offset); - enqueue_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset), value); + enqueue_if_weak_or_archive(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset), value); return value; } --- old/src/hotspot/share/oops/access.hpp 2018-01-09 13:49:20.071913445 +0100 +++ new/src/hotspot/share/oops/access.hpp 2018-01-09 13:49:19.791913454 +0100 @@ -200,12 +200,14 @@ const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 19; const DecoratorSet IN_ROOT = UCONST64(1) << 20; const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 21; +const DecoratorSet IN_ARCHIVE_ROOT = UCONST64(1) << 22; const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_HEAP_ARRAY | - IN_ROOT | IN_CONCURRENT_ROOT; + IN_ROOT | IN_CONCURRENT_ROOT | + IN_ARCHIVE_ROOT; // == Value Decorators == // * OOP_NOT_NULL: This property can make certain barriers faster such as compressing oops. -const DecoratorSet OOP_NOT_NULL = UCONST64(1) << 22; +const DecoratorSet OOP_NOT_NULL = UCONST64(1) << 23; const DecoratorSet OOP_DECORATOR_MASK = OOP_NOT_NULL; // == Arraycopy Decorators == --- old/src/hotspot/share/oops/access.inline.hpp 2018-01-09 13:49:20.931913415 +0100 +++ new/src/hotspot/share/oops/access.inline.hpp 2018-01-09 13:49:20.635913425 +0100 @@ -767,7 +767,9 @@ ((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 value = conc_root_is_root | BT_BUILDTIME_DECORATORS; + 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; }; // Step 2: Reduce types. @@ -1037,7 +1039,8 @@ (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_CONCURRENT_ROOT)) == 0 || + (location_decorators ^ (IN_ROOT | IN_ARCHIVE_ROOT)) == 0 )); } --- old/src/hotspot/share/oops/constantPool.cpp 2018-01-09 13:49:21.867913382 +0100 +++ new/src/hotspot/share/oops/constantPool.cpp 2018-01-09 13:49:21.587913392 +0100 @@ -49,9 +49,6 @@ #include "runtime/signature.hpp" #include "runtime/vframe.hpp" #include "utilities/copy.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // INCLUDE_ALL_GCS ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) { Array* tags = MetadataFactory::new_array(loader_data, length, 0, CHECK_NULL); @@ -330,17 +327,13 @@ if (SystemDictionary::Object_klass_loaded()) { ClassLoaderData* loader_data = pool_holder()->class_loader_data(); #if INCLUDE_CDS_JAVA_HEAP - if (MetaspaceShared::open_archive_heap_region_mapped() && - _cache->archived_references() != NULL) { + if (MetaspaceShared::open_archive_heap_region_mapped()) { oop archived = _cache->archived_references(); - // Make sure GC knows the cached object is now live. This is necessary after - // initial GC marking and during concurrent marking as strong roots are only - // scanned during initial marking (at the start of the GC marking). - assert(UseG1GC, "Requires G1 GC"); - G1SATBCardTableModRefBS::enqueue(archived); - // Create handle for the archived resolved reference array object - Handle refs_handle(THREAD, (oop)archived); - set_resolved_references(loader_data->add_handle(refs_handle)); + if (archived != NULL) { + // Create handle for the archived resolved reference array object + Handle refs_handle(THREAD, archived); + set_resolved_references(loader_data->add_handle(refs_handle)); + } } else #endif { --- old/src/hotspot/share/oops/cpCache.cpp 2018-01-09 13:49:22.775913350 +0100 +++ new/src/hotspot/share/oops/cpCache.cpp 2018-01-09 13:49:22.463913361 +0100 @@ -33,6 +33,7 @@ #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" +#include "oops/access.inline.hpp" #include "oops/cpCache.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" @@ -753,13 +754,16 @@ #if INCLUDE_CDS_JAVA_HEAP oop ConstantPoolCache::archived_references() { - assert(UseSharedSpaces, "UseSharedSpaces expected."); - return oopDesc::decode_heap_oop(_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); } void ConstantPoolCache::set_archived_references(oop o) { assert(DumpSharedSpaces, "called only during runtime"); - _archived_references = oopDesc::encode_heap_oop(o); + RootAccess::oop_store(&_archived_references, o); } #endif