< prev index next >
src/hotspot/share/memory/heapShared.cpp
Print this page
*** 22,48 ****
*
*/
#include "precompiled.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
#include "logging/logStream.hpp"
#include "memory/heapShared.inline.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
- #include "memory/metaspaceShared.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "utilities/bitMap.inline.hpp"
#if INCLUDE_CDS_JAVA_HEAP
KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
int HeapShared::_num_archived_subgraph_info_records = 0;
Array<ArchivedKlassSubGraphInfoRecord>* HeapShared::_archived_subgraph_info_records = NULL;
KlassSubGraphInfo* HeapShared::find_subgraph_info(Klass* k) {
--- 22,217 ----
*
*/
#include "precompiled.hpp"
#include "classfile/javaClasses.inline.hpp"
+ #include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
#include "logging/logStream.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/resourceArea.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
+ #include "runtime/safepointVerifiers.hpp"
#include "utilities/bitMap.inline.hpp"
+ #if INCLUDE_G1GC
+ #include "gc/g1/g1CollectedHeap.hpp"
+ #endif
#if INCLUDE_CDS_JAVA_HEAP
+
+ bool HeapShared::_open_archive_heap_region_mapped = false;
+ bool HeapShared::_archive_heap_region_fixed = false;
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // Java heap object archiving support
+ //
+ ////////////////////////////////////////////////////////////////
+ void HeapShared::fixup_mapped_heap_regions() {
+ FileMapInfo *mapinfo = FileMapInfo::current_info();
+ mapinfo->fixup_mapped_heap_regions();
+ set_archive_heap_region_fixed();
+ }
+
+ unsigned HeapShared::oop_hash(oop const& p) {
+ assert(!p->mark()->has_bias_pattern(),
+ "this object should never have been locked"); // so identity_hash won't safepoin
+ unsigned hash = (unsigned)p->identity_hash();
+ return hash;
+ }
+
+ HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = NULL;
+ oop HeapShared::find_archived_heap_object(oop obj) {
+ assert(DumpSharedSpaces, "dump-time only");
+ ArchivedObjectCache* cache = archived_object_cache();
+ oop* p = cache->get(obj);
+ if (p != NULL) {
+ return *p;
+ } else {
+ return NULL;
+ }
+ }
+
+ oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) {
+ assert(DumpSharedSpaces, "dump-time only");
+
+ oop ao = find_archived_heap_object(obj);
+ if (ao != NULL) {
+ // already archived
+ return ao;
+ }
+
+ int len = obj->size();
+ if (G1CollectedHeap::heap()->is_archive_alloc_too_large(len)) {
+ log_debug(cds, heap)("Cannot archive, object (" PTR_FORMAT ") is too large: " SIZE_FORMAT,
+ p2i(obj), (size_t)obj->size());
+ return NULL;
+ }
+
+ // Pre-compute object identity hash at CDS dump time.
+ obj->identity_hash();
+
+ oop archived_oop = (oop)G1CollectedHeap::heap()->archive_mem_allocate(len);
+ if (archived_oop != NULL) {
+ Copy::aligned_disjoint_words((HeapWord*)obj, (HeapWord*)archived_oop, len);
+ MetaspaceShared::relocate_klass_ptr(archived_oop);
+ ArchivedObjectCache* cache = archived_object_cache();
+ cache->put(obj, archived_oop);
+ log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT,
+ p2i(obj), p2i(archived_oop));
+ } else {
+ log_error(cds, heap)(
+ "Cannot allocate space for object " PTR_FORMAT " in archived heap region",
+ p2i(obj));
+ vm_exit(1);
+ }
+ return archived_oop;
+ }
+
+ oop HeapShared::materialize_archived_object(narrowOop v) {
+ assert(archive_heap_region_fixed(),
+ "must be called after archive heap regions are fixed");
+ if (!CompressedOops::is_null(v)) {
+ oop obj = HeapShared::decode_from_archive(v);
+ return G1CollectedHeap::heap()->materialize_archived_object(obj);
+ }
+ return NULL;
+ }
+
+ void HeapShared::archive_klass_objects(Thread* THREAD) {
+ GrowableArray<Klass*>* klasses = MetaspaceShared::collected_klasses();
+ assert(klasses != NULL, "sanity");
+ for (int i = 0; i < klasses->length(); i++) {
+ Klass* k = klasses->at(i);
+
+ // archive mirror object
+ java_lang_Class::archive_mirror(k, CHECK);
+
+ // archive the resolved_referenes array
+ if (k->is_instance_klass()) {
+ InstanceKlass* ik = InstanceKlass::cast(k);
+ ik->constants()->archive_resolved_references(THREAD);
+ }
+ }
+ }
+
+ void HeapShared::archive_java_heap_objects(GrowableArray<MemRegion> *closed,
+ GrowableArray<MemRegion> *open) {
+ if (!is_heap_object_archiving_allowed()) {
+ if (log_is_enabled(Info, cds)) {
+ log_info(cds)(
+ "Archived java heap is not supported as UseG1GC, "
+ "UseCompressedOops and UseCompressedClassPointers are required."
+ "Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.",
+ BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops),
+ BOOL_TO_STR(UseCompressedClassPointers));
+ }
+ return;
+ }
+
+ {
+ NoSafepointVerifier nsv;
+
+ // Cache for recording where the archived objects are copied to
+ create_archived_object_cache();
+
+ tty->print_cr("Dumping objects to closed archive heap region ...");
+ NOT_PRODUCT(StringTable::verify());
+ copy_closed_archive_heap_objects(closed);
+
+ tty->print_cr("Dumping objects to open archive heap region ...");
+ copy_open_archive_heap_objects(open);
+
+ destroy_archived_object_cache();
+ }
+
+ G1HeapVerifier::verify_archive_regions();
+ }
+
+ void HeapShared::copy_closed_archive_heap_objects(
+ GrowableArray<MemRegion> * closed_archive) {
+ assert(is_heap_object_archiving_allowed(), "Cannot archive java heap objects");
+
+ Thread* THREAD = Thread::current();
+ G1CollectedHeap::heap()->begin_archive_alloc_range();
+
+ // Archive interned string objects
+ StringTable::write_to_archive();
+
+ G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive,
+ os::vm_allocation_granularity());
+ }
+
+ void HeapShared::copy_open_archive_heap_objects(
+ GrowableArray<MemRegion> * open_archive) {
+ assert(is_heap_object_archiving_allowed(), "Cannot archive java heap objects");
+
+ Thread* THREAD = Thread::current();
+ G1CollectedHeap::heap()->begin_archive_alloc_range(true /* open */);
+
+ java_lang_Class::archive_basic_type_mirrors(THREAD);
+
+ archive_klass_objects(THREAD);
+
+ archive_object_subgraphs(THREAD);
+
+ G1CollectedHeap::heap()->end_archive_alloc_range(open_archive,
+ os::vm_allocation_granularity());
+ }
+
+ //
+ // Subgraph archiving support
+ //
KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
int HeapShared::_num_archived_subgraph_info_records = 0;
Array<ArchivedKlassSubGraphInfoRecord>* HeapShared::_archived_subgraph_info_records = NULL;
KlassSubGraphInfo* HeapShared::find_subgraph_info(Klass* k) {
*** 267,277 ****
buffer = (char*)_archived_subgraph_info_records + records_size;
return buffer;
}
void HeapShared::initialize_from_archived_subgraph(Klass* k) {
! if (!MetaspaceShared::open_archive_heap_region_mapped()) {
return; // nothing to do
}
if (_num_archived_subgraph_info_records == 0) {
return; // no subgraph info records
--- 436,446 ----
buffer = (char*)_archived_subgraph_info_records + records_size;
return buffer;
}
void HeapShared::initialize_from_archived_subgraph(Klass* k) {
! if (!open_archive_heap_region_mapped()) {
return; // nothing to do
}
if (_num_archived_subgraph_info_records == 0) {
return; // no subgraph info records
*** 324,335 ****
for (i = 0; i < efr_len;) {
int field_offset = entry_field_records->at(i);
// The object refereced by the field becomes 'known' by GC from this
// point. All objects in the subgraph reachable from the object are
// also 'known' by GC.
! oop v = MetaspaceShared::materialize_archived_object(
! entry_field_records->at(i+1));
m->obj_field_put(field_offset, v);
i += 2;
}
}
--- 493,503 ----
for (i = 0; i < efr_len;) {
int field_offset = entry_field_records->at(i);
// The object refereced by the field becomes 'known' by GC from this
// point. All objects in the subgraph reachable from the object are
// also 'known' by GC.
! oop v = materialize_archived_object(entry_field_records->at(i+1));
m->obj_field_put(field_offset, v);
i += 2;
}
}
*** 360,370 ****
protected:
template <class T> void do_oop_work(T *p) {
oop obj = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(obj)) {
! assert(!MetaspaceShared::is_archive_object(obj),
"original objects must not point to archived objects");
size_t field_delta = pointer_delta(p, _orig_referencing_obj, sizeof(char));
T* new_p = (T*)(address(_archived_referencing_obj) + field_delta);
Thread* THREAD = _thread;
--- 528,538 ----
protected:
template <class T> void do_oop_work(T *p) {
oop obj = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(obj)) {
! assert(!HeapShared::is_archived_object(obj),
"original objects must not point to archived objects");
size_t field_delta = pointer_delta(p, _orig_referencing_obj, sizeof(char));
T* new_p = (T*)(address(_archived_referencing_obj) + field_delta);
Thread* THREAD = _thread;
*** 379,389 ****
obj->print_on(&out);
}
oop archived = HeapShared::archive_reachable_objects_from(_level + 1, _subgraph_info, obj, THREAD);
assert(archived != NULL, "VM should have exited with unarchivable objects for _level > 1");
! assert(MetaspaceShared::is_archive_object(archived), "must be");
if (!_record_klasses_only) {
// Update the reference in the archived copy of the referencing object.
log_debug(cds, heap)("(%d) updating oop @[" PTR_FORMAT "] " PTR_FORMAT " ==> " PTR_FORMAT,
_level, p2i(new_p), p2i(obj), p2i(archived));
--- 547,557 ----
obj->print_on(&out);
}
oop archived = HeapShared::archive_reachable_objects_from(_level + 1, _subgraph_info, obj, THREAD);
assert(archived != NULL, "VM should have exited with unarchivable objects for _level > 1");
! assert(HeapShared::is_archived_object(archived), "must be");
if (!_record_klasses_only) {
// Update the reference in the archived copy of the referencing object.
log_debug(cds, heap)("(%d) updating oop @[" PTR_FORMAT "] " PTR_FORMAT " ==> " PTR_FORMAT,
_level, p2i(new_p), p2i(obj), p2i(archived));
*** 397,416 ****
// (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called),
// trace all objects that are reachable from it, and make sure these objects are archived.
// (3) Record the klasses of all orig_obj and all reachable objects.
oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS) {
assert(orig_obj != NULL, "must be");
! assert(!MetaspaceShared::is_archive_object(orig_obj), "sanity");
// java.lang.Class instances cannot be included in an archived
// object sub-graph.
if (java_lang_Class::is_instance(orig_obj)) {
log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level);
vm_exit(1);
}
! oop archived_obj = MetaspaceShared::find_archived_heap_object(orig_obj);
if (java_lang_String::is_instance(orig_obj) && archived_obj != NULL) {
// To save time, don't walk strings that are already archived. They just contain
// pointers to a type array, whose klass doesn't need to be recorded.
return archived_obj;
}
--- 565,584 ----
// (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called),
// trace all objects that are reachable from it, and make sure these objects are archived.
// (3) Record the klasses of all orig_obj and all reachable objects.
oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS) {
assert(orig_obj != NULL, "must be");
! assert(!is_archived_object(orig_obj), "sanity");
// java.lang.Class instances cannot be included in an archived
// object sub-graph.
if (java_lang_Class::is_instance(orig_obj)) {
log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level);
vm_exit(1);
}
! oop archived_obj = find_archived_heap_object(orig_obj);
if (java_lang_String::is_instance(orig_obj) && archived_obj != NULL) {
// To save time, don't walk strings that are already archived. They just contain
// pointers to a type array, whose klass doesn't need to be recorded.
return archived_obj;
}
*** 423,433 ****
}
bool record_klasses_only = (archived_obj != NULL);
if (archived_obj == NULL) {
++_num_new_archived_objs;
! archived_obj = MetaspaceShared::archive_heap_object(orig_obj, THREAD);
if (archived_obj == NULL) {
// Skip archiving the sub-graph referenced from the current entry field.
ResourceMark rm;
log_error(cds, heap)(
"Cannot archive the sub-graph referenced from %s object ("
--- 591,601 ----
}
bool record_klasses_only = (archived_obj != NULL);
if (archived_obj == NULL) {
++_num_new_archived_objs;
! archived_obj = archive_heap_object(orig_obj, THREAD);
if (archived_obj == NULL) {
// Skip archiving the sub-graph referenced from the current entry field.
ResourceMark rm;
log_error(cds, heap)(
"Cannot archive the sub-graph referenced from %s object ("
*** 497,507 ****
TRAPS) {
assert(DumpSharedSpaces, "dump time only");
assert(k->is_shared_boot_class(), "must be boot class");
oop m = k->java_mirror();
! oop archived_m = MetaspaceShared::find_archived_heap_object(m);
if (CompressedOops::is_null(archived_m)) {
return;
}
KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
--- 665,675 ----
TRAPS) {
assert(DumpSharedSpaces, "dump time only");
assert(k->is_shared_boot_class(), "must be boot class");
oop m = k->java_mirror();
! oop archived_m = find_archived_heap_object(m);
if (CompressedOops::is_null(archived_m)) {
return;
}
KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
*** 558,579 ****
void HeapShared::verify_subgraph_from_static_field(InstanceKlass* k, int field_offset) {
assert(DumpSharedSpaces, "dump time only");
assert(k->is_shared_boot_class(), "must be boot class");
oop m = k->java_mirror();
! oop archived_m = MetaspaceShared::find_archived_heap_object(m);
if (CompressedOops::is_null(archived_m)) {
return;
}
oop f = m->obj_field(field_offset);
if (!CompressedOops::is_null(f)) {
verify_subgraph_from(f);
}
}
void HeapShared::verify_subgraph_from(oop orig_obj) {
! oop archived_obj = MetaspaceShared::find_archived_heap_object(orig_obj);
if (archived_obj == NULL) {
// It's OK for the root of a subgraph to be not archived. See comments in
// archive_reachable_objects_from().
return;
}
--- 726,747 ----
void HeapShared::verify_subgraph_from_static_field(InstanceKlass* k, int field_offset) {
assert(DumpSharedSpaces, "dump time only");
assert(k->is_shared_boot_class(), "must be boot class");
oop m = k->java_mirror();
! oop archived_m = find_archived_heap_object(m);
if (CompressedOops::is_null(archived_m)) {
return;
}
oop f = m->obj_field(field_offset);
if (!CompressedOops::is_null(f)) {
verify_subgraph_from(f);
}
}
void HeapShared::verify_subgraph_from(oop orig_obj) {
! oop archived_obj = find_archived_heap_object(orig_obj);
if (archived_obj == NULL) {
// It's OK for the root of a subgraph to be not archived. See comments in
// archive_reachable_objects_from().
return;
}
*** 596,610 ****
_num_total_verifications ++;
if (!has_been_seen_during_subgraph_recording(obj)) {
set_has_been_seen_during_subgraph_recording(obj);
if (is_archived) {
! assert(MetaspaceShared::is_archive_object(obj), "must be");
! assert(MetaspaceShared::find_archived_heap_object(obj) == NULL, "must be");
} else {
! assert(!MetaspaceShared::is_archive_object(obj), "must be");
! assert(MetaspaceShared::find_archived_heap_object(obj) != NULL, "must be");
}
VerifySharedOopClosure walker(is_archived);
obj->oop_iterate(&walker);
}
--- 764,778 ----
_num_total_verifications ++;
if (!has_been_seen_during_subgraph_recording(obj)) {
set_has_been_seen_during_subgraph_recording(obj);
if (is_archived) {
! assert(is_archived_object(obj), "must be");
! assert(find_archived_heap_object(obj) == NULL, "must be");
} else {
! assert(!is_archived_object(obj), "must be");
! assert(find_archived_heap_object(obj) != NULL, "must be");
}
VerifySharedOopClosure walker(is_archived);
obj->oop_iterate(&walker);
}
*** 718,728 ****
info->klass = ik;
info->offset = finder.offset();
}
}
! void HeapShared::archive_static_fields(Thread* THREAD) {
// For each class X that has one or more archived fields:
// [1] Dump the subgraph of each archived field
// [2] Create a list of all the class of the objects that can be reached
// by any of these static fields.
// At runtime, these classes are initialized before X's archived fields
--- 886,896 ----
info->klass = ik;
info->offset = finder.offset();
}
}
! void HeapShared::archive_object_subgraphs(Thread* THREAD) {
// For each class X that has one or more archived fields:
// [1] Dump the subgraph of each archived field
// [2] Create a list of all the class of the objects that can be reached
// by any of these static fields.
// At runtime, these classes are initialized before X's archived fields
< prev index next >