8204585: Remove IN_ARCHIVE_ROOT from Access API

Replaced Access API with API on heap.

Co-authored-by: Stefan Karlsson <stefan.karlsson@oracle.com>
Reviewed-by: jiangli, coleenp, tschatzl
This commit is contained in:
Kim Barrett 2018-06-12 18:12:59 -04:00
parent ea01772a00
commit df34500027
14 changed files with 71 additions and 59 deletions

View file

@ -63,7 +63,6 @@
#include "runtime/vframe.inline.hpp" #include "runtime/vframe.inline.hpp"
#include "utilities/align.hpp" #include "utilities/align.hpp"
#include "utilities/preserveException.hpp" #include "utilities/preserveException.hpp"
#if INCLUDE_JVMCI #if INCLUDE_JVMCI
#include "jvmci/jvmciJavaClasses.hpp" #include "jvmci/jvmciJavaClasses.hpp"
#endif #endif
@ -809,12 +808,8 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) {
if (k->is_shared() && k->has_raw_archived_mirror()) { if (k->is_shared() && k->has_raw_archived_mirror()) {
if (MetaspaceShared::open_archive_heap_region_mapped()) { if (MetaspaceShared::open_archive_heap_region_mapped()) {
oop m = k->archived_java_mirror(); bool present = restore_archived_mirror(k, Handle(), Handle(), Handle(), CHECK);
assert(m != NULL, "archived mirror is NULL"); assert(present, "Missing archived mirror for %s", k->external_name());
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);
return; return;
} else { } else {
k->set_java_mirror_handle(NULL); k->set_java_mirror_handle(NULL);
@ -1207,11 +1202,23 @@ oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror,
return archived_mirror; return archived_mirror;
} }
// After the archived mirror object is restored, the shared klass' // Returns true if the mirror is updated, false if no archived mirror
// _has_raw_archived_mirror flag is cleared // data is present. After the archived mirror object is restored, the
void java_lang_Class::restore_archived_mirror(Klass *k, Handle mirror, // shared klass' _has_raw_archived_mirror flag is cleared.
bool java_lang_Class::restore_archived_mirror(Klass *k,
Handle class_loader, Handle module, Handle class_loader, Handle module,
Handle protection_domain, TRAPS) { Handle protection_domain, TRAPS) {
oop m = MetaspaceShared::materialize_archived_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. // 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 // No need to put classes on the fixup_mirror_list before java.lang.Class
@ -1221,7 +1228,7 @@ void java_lang_Class::restore_archived_mirror(Klass *k, Handle mirror,
// - local static final fields with initial values were initialized at dump time // - local static final fields with initial values were initialized at dump time
// create the init_lock // 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); set_init_lock(mirror(), r);
if (protection_domain.not_null()) { if (protection_domain.not_null()) {
@ -1241,6 +1248,8 @@ void java_lang_Class::restore_archived_mirror(Klass *k, Handle mirror,
ResourceMark rm; ResourceMark rm;
log_trace(cds, mirror)("Restored %s archived mirror " PTR_FORMAT, k->external_name(), p2i(mirror())); log_trace(cds, mirror)("Restored %s archived mirror " PTR_FORMAT, k->external_name(), p2i(mirror()));
return true;
} }
#endif // INCLUDE_CDS_JAVA_HEAP #endif // INCLUDE_CDS_JAVA_HEAP

View file

@ -229,8 +229,9 @@ class java_lang_Class : AllStatic {
static oop archive_mirror(Klass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(NULL); 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) static oop process_archived_mirror(Klass* k, oop mirror, oop archived_mirror, Thread *THREAD)
NOT_CDS_JAVA_HEAP_RETURN_(NULL); NOT_CDS_JAVA_HEAP_RETURN_(NULL);
static void restore_archived_mirror(Klass *k, Handle mirror, Handle class_loader, Handle module, static bool restore_archived_mirror(Klass *k, Handle class_loader, Handle module,
Handle protection_domain, TRAPS) NOT_CDS_JAVA_HEAP_RETURN; Handle protection_domain,
TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(false);
static void fixup_module_field(Klass* k, Handle module); static void fixup_module_field(Klass* k, Handle module);

View file

@ -50,7 +50,7 @@ class G1BarrierSet: public CardTableBarrierSet {
// pre-marking object graph. // pre-marking object graph.
static void enqueue(oop pre_val); 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 <class T> void write_ref_array_pre_work(T* dst, size_t count); template <class T> 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); virtual void write_ref_array_pre(oop* dst, size_t count, bool dest_uninitialized);

View file

@ -54,15 +54,14 @@ inline void G1BarrierSet::write_ref_field_post(T* field, oop new_val) {
} }
} }
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"); assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known");
// Archive roots need to be enqueued since they add subgraphs to the // Loading from a weak or phantom reference needs enqueueing, as
// Java heap that were not there at the snapshot when marking started. // the object may not have been reachable (part of the snapshot)
// Weak and phantom references also need enqueueing for similar reasons. // when marking started.
const bool in_archive_root = (decorators & IN_ARCHIVE_ROOT) != 0;
const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0; const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0;
const bool peek = (decorators & AS_NO_KEEPALIVE) != 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) { if (needs_enqueue && value != NULL) {
enqueue(value); enqueue(value);
@ -74,7 +73,7 @@ template <typename T>
inline oop G1BarrierSet::AccessBarrier<decorators, BarrierSetT>:: inline oop G1BarrierSet::AccessBarrier<decorators, BarrierSetT>::
oop_load_not_in_heap(T* addr) { oop_load_not_in_heap(T* addr) {
oop value = ModRef::oop_load_not_in_heap(addr); oop value = ModRef::oop_load_not_in_heap(addr);
enqueue_if_weak_or_archive(decorators, value); enqueue_if_weak(decorators, value);
return value; return value;
} }
@ -83,7 +82,7 @@ template <typename T>
inline oop G1BarrierSet::AccessBarrier<decorators, BarrierSetT>:: inline oop G1BarrierSet::AccessBarrier<decorators, BarrierSetT>::
oop_load_in_heap(T* addr) { oop_load_in_heap(T* addr) {
oop value = ModRef::oop_load_in_heap(addr); oop value = ModRef::oop_load_in_heap(addr);
enqueue_if_weak_or_archive(decorators, value); enqueue_if_weak(decorators, value);
return value; return value;
} }
@ -91,7 +90,7 @@ template <DecoratorSet decorators, typename BarrierSetT>
inline oop G1BarrierSet::AccessBarrier<decorators, BarrierSetT>:: inline oop G1BarrierSet::AccessBarrier<decorators, BarrierSetT>::
oop_load_in_heap_at(oop base, ptrdiff_t offset) { oop_load_in_heap_at(oop base, ptrdiff_t offset) {
oop value = ModRef::oop_load_in_heap_at(base, offset); oop value = ModRef::oop_load_in_heap_at(base, offset);
enqueue_if_weak_or_archive(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), value); enqueue_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), value);
return value; return value;
} }

View file

@ -78,6 +78,7 @@
#include "logging/log.hpp" #include "logging/log.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "memory/iterator.hpp" #include "memory/iterator.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp" #include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp" #include "oops/compressedOops.inline.hpp"
@ -823,6 +824,18 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
decrease_used(size_used); 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) { HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) {
ResourceMark rm; // For retrieving the thread names in log messages. ResourceMark rm; // For retrieving the thread names in log messages.

View file

@ -699,6 +699,8 @@ public:
// mapping failed, with the same non-overlapping and sorted MemRegion array. // mapping failed, with the same non-overlapping and sorted MemRegion array.
void dealloc_archive_regions(MemRegion* range, size_t count); void dealloc_archive_regions(MemRegion* range, size_t count);
oop materialize_archived_object(oop obj);
private: private:
// Shrink the garbage-first heap by at most the given size (in bytes!). // Shrink the garbage-first heap by at most the given size (in bytes!).

View file

@ -45,7 +45,6 @@ ZBarrierSetAssembler* ZBarrierSet::assembler() {
bool ZBarrierSet::barrier_needed(DecoratorSet decorators, BasicType type) { bool ZBarrierSet::barrier_needed(DecoratorSet decorators, BasicType type) {
assert((decorators & AS_RAW) == 0, "Unexpected decorator"); assert((decorators & AS_RAW) == 0, "Unexpected decorator");
assert((decorators & AS_NO_KEEPALIVE) == 0, "Unexpected decorator"); assert((decorators & AS_NO_KEEPALIVE) == 0, "Unexpected decorator");
assert((decorators & IN_ARCHIVE_ROOT) == 0, "Unexpected decorator");
//assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Unexpected decorator"); //assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Unexpected decorator");
if (type == T_OBJECT || type == T_ARRAY) { if (type == T_OBJECT || type == T_ARRAY) {

View file

@ -1910,6 +1910,11 @@ oop MetaspaceShared::archive_heap_object(oop obj, Thread* THREAD) {
return archived_oop; return archived_oop;
} }
oop MetaspaceShared::materialize_archived_object(oop obj) {
assert(obj != NULL, "sanity");
return G1CollectedHeap::heap()->materialize_archived_object(obj);
}
void MetaspaceShared::archive_klass_objects(Thread* THREAD) { void MetaspaceShared::archive_klass_objects(Thread* THREAD) {
int i; int i;
for (i = 0; i < _global_klass_objects->length(); i++) { for (i = 0; i < _global_klass_objects->length(); i++) {
@ -1980,7 +1985,7 @@ public:
"Archived heap object is not allowed"); "Archived heap object is not allowed");
assert(MetaspaceShared::open_archive_heap_region_mapped(), assert(MetaspaceShared::open_archive_heap_region_mapped(),
"Open archive heap region is not mapped"); "Open archive heap region is not mapped");
RootAccess<IN_ARCHIVE_ROOT>::oop_store(p, CompressedOops::decode_not_null(o)); *p = CompressedOops::decode_not_null(o);
} }
} }

View file

@ -111,6 +111,7 @@ class MetaspaceShared : AllStatic {
} }
static oop find_archived_heap_object(oop obj); static oop find_archived_heap_object(oop obj);
static oop archive_heap_object(oop obj, Thread* THREAD); static oop archive_heap_object(oop obj, Thread* THREAD);
static oop materialize_archived_object(oop obj);
static void archive_klass_objects(Thread* THREAD); static void archive_klass_objects(Thread* THREAD);
#endif #endif

View file

@ -379,8 +379,7 @@ void Access<decorators>::verify_decorators() {
(location_decorators ^ IN_ROOT) == 0 || (location_decorators ^ IN_ROOT) == 0 ||
(location_decorators ^ IN_HEAP) == 0 || (location_decorators ^ IN_HEAP) == 0 ||
(location_decorators ^ (IN_HEAP | IN_HEAP_ARRAY)) == 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
)); ));
} }

View file

@ -192,10 +192,8 @@ const DecoratorSet IN_HEAP = UCONST64(1) << 20;
const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 21; const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 21;
const DecoratorSet IN_ROOT = UCONST64(1) << 22; const DecoratorSet IN_ROOT = UCONST64(1) << 22;
const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 23; 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 | 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 == // == Value Decorators ==
// * OOP_NOT_NULL: This property can make certain barriers faster such as compressing oops. // * OOP_NOT_NULL: This property can make certain barriers faster such as compressing oops.
@ -245,9 +243,7 @@ namespace AccessInternal {
((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY); ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY);
static const DecoratorSet conc_root_is_root = heap_array_is_in_heap | 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); ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY);
static const DecoratorSet archive_root_is_root = conc_root_is_root | static const DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS;
((IN_ARCHIVE_ROOT & conc_root_is_root) != 0 ? IN_ROOT : INTERNAL_EMPTY);
static const DecoratorSet value = archive_root_is_root | BT_BUILDTIME_DECORATORS;
}; };
// This function implements the above DecoratorFixup rules, but without meta // This function implements the above DecoratorFixup rules, but without meta
@ -268,9 +264,7 @@ namespace AccessInternal {
((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY); ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY);
DecoratorSet conc_root_is_root = heap_array_is_in_heap | DecoratorSet conc_root_is_root = heap_array_is_in_heap |
((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY); ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY);
DecoratorSet archive_root_is_root = conc_root_is_root | DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS;
((IN_ARCHIVE_ROOT & conc_root_is_root) != 0 ? IN_ROOT : INTERNAL_EMPTY);
DecoratorSet value = archive_root_is_root | BT_BUILDTIME_DECORATORS;
return value; return value;
} }
} }

View file

@ -32,6 +32,7 @@
#include "logging/log.hpp" #include "logging/log.hpp"
#include "memory/metadataFactory.hpp" #include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp" #include "memory/metaspaceClosure.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "oops/access.inline.hpp" #include "oops/access.inline.hpp"
@ -743,16 +744,15 @@ void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
#if INCLUDE_CDS_JAVA_HEAP #if INCLUDE_CDS_JAVA_HEAP
oop ConstantPoolCache::archived_references() { oop ConstantPoolCache::archived_references() {
// Loading an archive root forces the oop to become strongly reachable. if (CompressedOops::is_null(_archived_references)) {
// For example, if it is loaded during concurrent marking in a SATB return NULL;
// collector, it will be enqueued to the SATB queue, effectively }
// shading the previously white object gray. return MetaspaceShared::materialize_archived_object(CompressedOops::decode_not_null(_archived_references));
return RootAccess<IN_ARCHIVE_ROOT>::oop_load(&_archived_references);
} }
void ConstantPoolCache::set_archived_references(oop o) { void ConstantPoolCache::set_archived_references(oop o) {
assert(DumpSharedSpaces, "called only during runtime"); assert(DumpSharedSpaces, "called only during runtime");
RootAccess<IN_ARCHIVE_ROOT>::oop_store(&_archived_references, o); _archived_references = CompressedOops::encode(o);
} }
#endif #endif

View file

@ -529,20 +529,19 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
Handle module_handle(THREAD, ((module_entry != NULL) ? module_entry->module() : (oop)NULL)); Handle module_handle(THREAD, ((module_entry != NULL) ? module_entry->module() : (oop)NULL));
if (this->has_raw_archived_mirror()) { if (this->has_raw_archived_mirror()) {
ResourceMark rm;
log_debug(cds, mirror)("%s has raw archived mirror", external_name()); log_debug(cds, mirror)("%s has raw archived mirror", external_name());
if (MetaspaceShared::open_archive_heap_region_mapped()) { if (MetaspaceShared::open_archive_heap_region_mapped()) {
oop m = archived_java_mirror(); bool present = java_lang_Class::restore_archived_mirror(this, loader, module_handle,
log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m)); protection_domain,
if (m != NULL) { CHECK);
// mirror is archived, restore if (present) {
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);
return; return;
} }
} }
// No archived mirror data // No archived mirror data
log_debug(cds, mirror)("No archived mirror data for %s", external_name());
_java_mirror = NULL; _java_mirror = NULL;
this->clear_has_raw_archived_mirror(); this->clear_has_raw_archived_mirror();
} }
@ -558,18 +557,10 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
#if INCLUDE_CDS_JAVA_HEAP #if INCLUDE_CDS_JAVA_HEAP
// Used at CDS dump time to access the archived mirror. No GC barrier. // Used at CDS dump time to access the archived mirror. No GC barrier.
oop Klass::archived_java_mirror_raw() { oop Klass::archived_java_mirror_raw() {
assert(DumpSharedSpaces, "called only during runtime");
assert(has_raw_archived_mirror(), "must have raw archived mirror"); assert(has_raw_archived_mirror(), "must have raw archived mirror");
return CompressedOops::decode(_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<IN_ARCHIVE_ROOT>::oop_load(&_archived_mirror);
}
// No GC barrier // No GC barrier
void Klass::set_archived_java_mirror_raw(oop m) { void Klass::set_archived_java_mirror_raw(oop m) {
assert(DumpSharedSpaces, "called only during runtime"); assert(DumpSharedSpaces, "called only during runtime");

View file

@ -244,7 +244,6 @@ protected:
void set_java_mirror(Handle m); void set_java_mirror(Handle m);
oop archived_java_mirror_raw() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // no GC barrier 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 void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier
// Temporary mirror switch used by RedefineClasses // Temporary mirror switch used by RedefineClasses