< 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 >