35 #include "memory/iterator.inline.hpp" |
35 #include "memory/iterator.inline.hpp" |
36 #include "memory/metadataFactory.hpp" |
36 #include "memory/metadataFactory.hpp" |
37 #include "memory/metaspaceClosure.hpp" |
37 #include "memory/metaspaceClosure.hpp" |
38 #include "memory/resourceArea.hpp" |
38 #include "memory/resourceArea.hpp" |
39 #include "oops/compressedOops.inline.hpp" |
39 #include "oops/compressedOops.inline.hpp" |
|
40 #include "oops/fieldStreams.hpp" |
40 #include "oops/oop.inline.hpp" |
41 #include "oops/oop.inline.hpp" |
41 #include "runtime/fieldDescriptor.inline.hpp" |
42 #include "runtime/fieldDescriptor.inline.hpp" |
42 #include "runtime/safepointVerifiers.hpp" |
43 #include "runtime/safepointVerifiers.hpp" |
43 #include "utilities/bitMap.inline.hpp" |
44 #include "utilities/bitMap.inline.hpp" |
44 #if INCLUDE_G1GC |
45 #if INCLUDE_G1GC |
45 #include "gc/g1/g1CollectedHeap.hpp" |
46 #include "gc/g1/g1CollectedHeap.hpp" |
46 #endif |
47 #endif |
47 |
48 |
48 #if INCLUDE_CDS_JAVA_HEAP |
49 #if INCLUDE_CDS_JAVA_HEAP |
49 |
50 |
|
51 bool HeapShared::_closed_archive_heap_region_mapped = false; |
50 bool HeapShared::_open_archive_heap_region_mapped = false; |
52 bool HeapShared::_open_archive_heap_region_mapped = false; |
51 bool HeapShared::_archive_heap_region_fixed = false; |
53 bool HeapShared::_archive_heap_region_fixed = false; |
52 |
54 |
53 address HeapShared::_narrow_oop_base; |
55 address HeapShared::_narrow_oop_base; |
54 int HeapShared::_narrow_oop_shift; |
56 int HeapShared::_narrow_oop_shift; |
|
57 |
|
58 // |
|
59 // If you add new entries to the following tables, you should know what you're doing! |
|
60 // |
|
61 |
|
62 // Entry fields for shareable subgraphs archived in the closed archive heap |
|
63 // region. Warning: Objects in the subgraphs should not have reference fields |
|
64 // assigned at runtime. |
|
65 static ArchivableStaticFieldInfo closed_archive_subgraph_entry_fields[] = { |
|
66 {"java/lang/Integer$IntegerCache", "archivedCache"}, |
|
67 }; |
|
68 // Entry fields for subgraphs archived in the open archive heap region. |
|
69 static ArchivableStaticFieldInfo open_archive_subgraph_entry_fields[] = { |
|
70 {"jdk/internal/module/ArchivedModuleGraph", "archivedSystemModules"}, |
|
71 {"jdk/internal/module/ArchivedModuleGraph", "archivedModuleFinder"}, |
|
72 {"jdk/internal/module/ArchivedModuleGraph", "archivedMainModule"}, |
|
73 {"jdk/internal/module/ArchivedModuleGraph", "archivedConfiguration"}, |
|
74 {"java/util/ImmutableCollections$ListN", "EMPTY_LIST"}, |
|
75 {"java/util/ImmutableCollections$MapN", "EMPTY_MAP"}, |
|
76 {"java/util/ImmutableCollections$SetN", "EMPTY_SET"}, |
|
77 {"java/lang/module/Configuration", "EMPTY_CONFIGURATION"}, |
|
78 }; |
|
79 |
|
80 const static int num_closed_archive_subgraph_entry_fields = |
|
81 sizeof(closed_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo); |
|
82 const static int num_open_archive_subgraph_entry_fields = |
|
83 sizeof(open_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo); |
55 |
84 |
56 //////////////////////////////////////////////////////////////// |
85 //////////////////////////////////////////////////////////////// |
57 // |
86 // |
58 // Java heap object archiving support |
87 // Java heap object archiving support |
59 // |
88 // |
235 } |
271 } |
236 return info; |
272 return info; |
237 } |
273 } |
238 |
274 |
239 // Add an entry field to the current KlassSubGraphInfo. |
275 // Add an entry field to the current KlassSubGraphInfo. |
240 void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) { |
276 void KlassSubGraphInfo::add_subgraph_entry_field( |
|
277 int static_field_offset, oop v, bool is_closed_archive) { |
241 assert(DumpSharedSpaces, "dump time only"); |
278 assert(DumpSharedSpaces, "dump time only"); |
242 if (_subgraph_entry_fields == NULL) { |
279 if (_subgraph_entry_fields == NULL) { |
243 _subgraph_entry_fields = |
280 _subgraph_entry_fields = |
244 new(ResourceObj::C_HEAP, mtClass) GrowableArray<juint>(10, true); |
281 new(ResourceObj::C_HEAP, mtClass) GrowableArray<juint>(10, true); |
245 } |
282 } |
246 _subgraph_entry_fields->append((juint)static_field_offset); |
283 _subgraph_entry_fields->append((juint)static_field_offset); |
247 _subgraph_entry_fields->append(CompressedOops::encode(v)); |
284 _subgraph_entry_fields->append(CompressedOops::encode(v)); |
|
285 _subgraph_entry_fields->append(is_closed_archive ? 1 : 0); |
248 } |
286 } |
249 |
287 |
250 // Add the Klass* for an object in the current KlassSubGraphInfo's subgraphs. |
288 // Add the Klass* for an object in the current KlassSubGraphInfo's subgraphs. |
251 // Only objects of boot classes can be included in sub-graph. |
289 // Only objects of boot classes can be included in sub-graph. |
252 void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k, Klass *relocated_k) { |
290 void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k, Klass *relocated_k) { |
363 }; |
401 }; |
364 |
402 |
365 // Build the records of archived subgraph infos, which include: |
403 // Build the records of archived subgraph infos, which include: |
366 // - Entry points to all subgraphs from the containing class mirror. The entry |
404 // - Entry points to all subgraphs from the containing class mirror. The entry |
367 // points are static fields in the mirror. For each entry point, the field |
405 // points are static fields in the mirror. For each entry point, the field |
368 // offset and value are recorded in the sub-graph info. The value are stored |
406 // offset, value and is_closed_archive flag are recorded in the sub-graph |
369 // back to the corresponding field at runtime. |
407 // info. The value is stored back to the corresponding field at runtime. |
370 // - A list of klasses that need to be loaded/initialized before archived |
408 // - A list of klasses that need to be loaded/initialized before archived |
371 // java object sub-graph can be accessed at runtime. |
409 // java object sub-graph can be accessed at runtime. |
372 void HeapShared::write_subgraph_info_table() { |
410 void HeapShared::write_subgraph_info_table() { |
373 // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive. |
411 // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive. |
374 DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table; |
412 DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table; |
446 // the corresponding fields within the mirror. |
484 // the corresponding fields within the mirror. |
447 oop m = k->java_mirror(); |
485 oop m = k->java_mirror(); |
448 Array<juint>* entry_field_records = record->entry_field_records(); |
486 Array<juint>* entry_field_records = record->entry_field_records(); |
449 if (entry_field_records != NULL) { |
487 if (entry_field_records != NULL) { |
450 int efr_len = entry_field_records->length(); |
488 int efr_len = entry_field_records->length(); |
451 assert(efr_len % 2 == 0, "sanity"); |
489 assert(efr_len % 3 == 0, "sanity"); |
452 for (i = 0; i < efr_len;) { |
490 for (i = 0; i < efr_len;) { |
453 int field_offset = entry_field_records->at(i); |
491 int field_offset = entry_field_records->at(i); |
454 // The object refereced by the field becomes 'known' by GC from this |
492 narrowOop nv = entry_field_records->at(i+1); |
455 // point. All objects in the subgraph reachable from the object are |
493 int is_closed_archive = entry_field_records->at(i+2); |
456 // also 'known' by GC. |
494 oop v; |
457 oop v = materialize_archived_object(entry_field_records->at(i+1)); |
495 if (is_closed_archive == 0) { |
|
496 // It's an archived object in the open archive heap regions, not shared. |
|
497 // The object refereced by the field becomes 'known' by GC from this |
|
498 // point. All objects in the subgraph reachable from the object are |
|
499 // also 'known' by GC. |
|
500 v = materialize_archived_object(nv); |
|
501 } else { |
|
502 // Shared object in the closed archive heap regions. Decode directly. |
|
503 assert(!CompressedOops::is_null(nv), "shared object is null"); |
|
504 v = HeapShared::decode_from_archive(nv); |
|
505 } |
458 m->obj_field_put(field_offset, v); |
506 m->obj_field_put(field_offset, v); |
459 i += 2; |
507 i += 3; |
460 |
508 |
461 log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v)); |
509 log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v)); |
462 } |
510 } |
463 |
511 |
464 // Done. Java code can see the archived sub-graphs referenced from k's |
512 // Done. Java code can see the archived sub-graphs referenced from k's |
467 } |
515 } |
468 } |
516 } |
469 |
517 |
470 class WalkOopAndArchiveClosure: public BasicOopIterateClosure { |
518 class WalkOopAndArchiveClosure: public BasicOopIterateClosure { |
471 int _level; |
519 int _level; |
|
520 bool _is_closed_archive; |
472 bool _record_klasses_only; |
521 bool _record_klasses_only; |
473 KlassSubGraphInfo* _subgraph_info; |
522 KlassSubGraphInfo* _subgraph_info; |
474 oop _orig_referencing_obj; |
523 oop _orig_referencing_obj; |
475 oop _archived_referencing_obj; |
524 oop _archived_referencing_obj; |
476 Thread* _thread; |
525 Thread* _thread; |
477 public: |
526 public: |
478 WalkOopAndArchiveClosure(int level, bool record_klasses_only, |
527 WalkOopAndArchiveClosure(int level, |
|
528 bool is_closed_archive, |
|
529 bool record_klasses_only, |
479 KlassSubGraphInfo* subgraph_info, |
530 KlassSubGraphInfo* subgraph_info, |
480 oop orig, oop archived, TRAPS) : |
531 oop orig, oop archived, TRAPS) : |
481 _level(level), _record_klasses_only(record_klasses_only), |
532 _level(level), _is_closed_archive(is_closed_archive), |
|
533 _record_klasses_only(record_klasses_only), |
482 _subgraph_info(subgraph_info), |
534 _subgraph_info(subgraph_info), |
483 _orig_referencing_obj(orig), _archived_referencing_obj(archived), |
535 _orig_referencing_obj(orig), _archived_referencing_obj(archived), |
484 _thread(THREAD) {} |
536 _thread(THREAD) {} |
485 void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } |
537 void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } |
486 void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } |
538 void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } |
518 } |
571 } |
519 } |
572 } |
520 } |
573 } |
521 }; |
574 }; |
522 |
575 |
|
576 void HeapShared::check_closed_archive_heap_region_object(InstanceKlass* k, |
|
577 Thread* THREAD) { |
|
578 // Check fields in the object |
|
579 for (JavaFieldStream fs(k); !fs.done(); fs.next()) { |
|
580 if (!fs.access_flags().is_static()) { |
|
581 BasicType ft = fs.field_descriptor().field_type(); |
|
582 if (!fs.access_flags().is_final() && (ft == T_ARRAY || T_OBJECT)) { |
|
583 ResourceMark rm(THREAD); |
|
584 log_warning(cds, heap)( |
|
585 "Please check reference field in %s instance in closed archive heap region: %s %s", |
|
586 k->external_name(), (fs.name())->as_C_string(), |
|
587 (fs.signature())->as_C_string()); |
|
588 } |
|
589 } |
|
590 } |
|
591 } |
|
592 |
523 // (1) If orig_obj has not been archived yet, archive it. |
593 // (1) If orig_obj has not been archived yet, archive it. |
524 // (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called), |
594 // (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called), |
525 // trace all objects that are reachable from it, and make sure these objects are archived. |
595 // trace all objects that are reachable from it, and make sure these objects are archived. |
526 // (3) Record the klasses of all orig_obj and all reachable objects. |
596 // (3) Record the klasses of all orig_obj and all reachable objects. |
527 oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS) { |
597 oop HeapShared::archive_reachable_objects_from(int level, |
|
598 KlassSubGraphInfo* subgraph_info, |
|
599 oop orig_obj, |
|
600 bool is_closed_archive, |
|
601 TRAPS) { |
528 assert(orig_obj != NULL, "must be"); |
602 assert(orig_obj != NULL, "must be"); |
529 assert(!is_archived_object(orig_obj), "sanity"); |
603 assert(!is_archived_object(orig_obj), "sanity"); |
530 |
604 |
531 // java.lang.Class instances cannot be included in an archived |
605 // java.lang.Class instances cannot be included in an archived |
532 // object sub-graph. |
606 // object sub-graph. |
576 assert(archived_obj != NULL, "must be"); |
650 assert(archived_obj != NULL, "must be"); |
577 Klass *orig_k = orig_obj->klass(); |
651 Klass *orig_k = orig_obj->klass(); |
578 Klass *relocated_k = archived_obj->klass(); |
652 Klass *relocated_k = archived_obj->klass(); |
579 subgraph_info->add_subgraph_object_klass(orig_k, relocated_k); |
653 subgraph_info->add_subgraph_object_klass(orig_k, relocated_k); |
580 |
654 |
581 WalkOopAndArchiveClosure walker(level, record_klasses_only, subgraph_info, orig_obj, archived_obj, THREAD); |
655 WalkOopAndArchiveClosure walker(level, is_closed_archive, record_klasses_only, |
|
656 subgraph_info, orig_obj, archived_obj, THREAD); |
582 orig_obj->oop_iterate(&walker); |
657 orig_obj->oop_iterate(&walker); |
|
658 if (is_closed_archive && orig_k->is_instance_klass()) { |
|
659 check_closed_archive_heap_region_object(InstanceKlass::cast(orig_k), THREAD); |
|
660 } |
583 return archived_obj; |
661 return archived_obj; |
584 } |
662 } |
585 |
663 |
586 // |
664 // |
587 // Start from the given static field in a java mirror and archive the |
665 // Start from the given static field in a java mirror and archive the |
619 // |
697 // |
620 void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k, |
698 void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k, |
621 const char* klass_name, |
699 const char* klass_name, |
622 int field_offset, |
700 int field_offset, |
623 const char* field_name, |
701 const char* field_name, |
|
702 bool is_closed_archive, |
624 TRAPS) { |
703 TRAPS) { |
625 assert(DumpSharedSpaces, "dump time only"); |
704 assert(DumpSharedSpaces, "dump time only"); |
626 assert(k->is_shared_boot_class(), "must be boot class"); |
705 assert(k->is_shared_boot_class(), "must be boot class"); |
627 |
706 |
628 oop m = k->java_mirror(); |
707 oop m = k->java_mirror(); |
629 oop archived_m = find_archived_heap_object(m); |
|
630 if (CompressedOops::is_null(archived_m)) { |
|
631 return; |
|
632 } |
|
633 |
708 |
634 KlassSubGraphInfo* subgraph_info = get_subgraph_info(k); |
709 KlassSubGraphInfo* subgraph_info = get_subgraph_info(k); |
635 oop f = m->obj_field(field_offset); |
710 oop f = m->obj_field(field_offset); |
636 |
711 |
637 log_debug(cds, heap)("Start archiving from: %s::%s (" PTR_FORMAT ")", klass_name, field_name, p2i(f)); |
712 log_debug(cds, heap)("Start archiving from: %s::%s (" PTR_FORMAT ")", klass_name, field_name, p2i(f)); |
641 LogTarget(Trace, cds, heap) log; |
716 LogTarget(Trace, cds, heap) log; |
642 LogStream out(log); |
717 LogStream out(log); |
643 f->print_on(&out); |
718 f->print_on(&out); |
644 } |
719 } |
645 |
720 |
646 oop af = archive_reachable_objects_from(1, subgraph_info, f, CHECK); |
721 oop af = archive_reachable_objects_from(1, subgraph_info, f, |
|
722 is_closed_archive, CHECK); |
647 |
723 |
648 if (af == NULL) { |
724 if (af == NULL) { |
649 log_error(cds, heap)("Archiving failed %s::%s (some reachable objects cannot be archived)", |
725 log_error(cds, heap)("Archiving failed %s::%s (some reachable objects cannot be archived)", |
650 klass_name, field_name); |
726 klass_name, field_name); |
651 } else { |
727 } else { |
652 // Note: the field value is not preserved in the archived mirror. |
728 // Note: the field value is not preserved in the archived mirror. |
653 // Record the field as a new subGraph entry point. The recorded |
729 // Record the field as a new subGraph entry point. The recorded |
654 // information is restored from the archive at runtime. |
730 // information is restored from the archive at runtime. |
655 subgraph_info->add_subgraph_entry_field(field_offset, af); |
731 subgraph_info->add_subgraph_entry_field(field_offset, af, is_closed_archive); |
656 log_info(cds, heap)("Archived field %s::%s => " PTR_FORMAT, klass_name, field_name, p2i(af)); |
732 log_info(cds, heap)("Archived field %s::%s => " PTR_FORMAT, klass_name, field_name, p2i(af)); |
657 } |
733 } |
658 } else { |
734 } else { |
659 // The field contains null, we still need to record the entry point, |
735 // The field contains null, we still need to record the entry point, |
660 // so it can be restored at runtime. |
736 // so it can be restored at runtime. |
661 subgraph_info->add_subgraph_entry_field(field_offset, NULL); |
737 subgraph_info->add_subgraph_entry_field(field_offset, NULL, false); |
662 } |
738 } |
663 } |
739 } |
664 |
740 |
665 #ifndef PRODUCT |
741 #ifndef PRODUCT |
666 class VerifySharedOopClosure: public BasicOopIterateClosure { |
742 class VerifySharedOopClosure: public BasicOopIterateClosure { |
780 _num_total_subgraph_recordings ++; |
852 _num_total_subgraph_recordings ++; |
781 _num_total_walked_objs += _num_new_walked_objs; |
853 _num_total_walked_objs += _num_new_walked_objs; |
782 _num_total_archived_objs += _num_new_archived_objs; |
854 _num_total_archived_objs += _num_new_archived_objs; |
783 _num_total_recorded_klasses += num_new_recorded_klasses; |
855 _num_total_recorded_klasses += num_new_recorded_klasses; |
784 } |
856 } |
785 |
|
786 struct ArchivableStaticFieldInfo { |
|
787 const char* klass_name; |
|
788 const char* field_name; |
|
789 InstanceKlass* klass; |
|
790 int offset; |
|
791 BasicType type; |
|
792 }; |
|
793 |
|
794 // If you add new entries to this table, you should know what you're doing! |
|
795 static ArchivableStaticFieldInfo archivable_static_fields[] = { |
|
796 {"jdk/internal/module/ArchivedModuleGraph", "archivedSystemModules"}, |
|
797 {"jdk/internal/module/ArchivedModuleGraph", "archivedModuleFinder"}, |
|
798 {"jdk/internal/module/ArchivedModuleGraph", "archivedMainModule"}, |
|
799 {"jdk/internal/module/ArchivedModuleGraph", "archivedConfiguration"}, |
|
800 {"java/util/ImmutableCollections$ListN", "EMPTY_LIST"}, |
|
801 {"java/util/ImmutableCollections$MapN", "EMPTY_MAP"}, |
|
802 {"java/util/ImmutableCollections$SetN", "EMPTY_SET"}, |
|
803 {"java/lang/Integer$IntegerCache", "archivedCache"}, |
|
804 {"java/lang/module/Configuration", "EMPTY_CONFIGURATION"}, |
|
805 }; |
|
806 |
|
807 const static int num_archivable_static_fields = |
|
808 sizeof(archivable_static_fields) / sizeof(ArchivableStaticFieldInfo); |
|
809 |
857 |
810 class ArchivableStaticFieldFinder: public FieldClosure { |
858 class ArchivableStaticFieldFinder: public FieldClosure { |
811 InstanceKlass* _ik; |
859 InstanceKlass* _ik; |
812 Symbol* _field_name; |
860 Symbol* _field_name; |
813 bool _found; |
861 bool _found; |
826 } |
874 } |
827 bool found() { return _found; } |
875 bool found() { return _found; } |
828 int offset() { return _offset; } |
876 int offset() { return _offset; } |
829 }; |
877 }; |
830 |
878 |
831 void HeapShared::init_archivable_static_fields(Thread* THREAD) { |
879 void HeapShared::init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[], |
832 _dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable(); |
880 int num, Thread* THREAD) { |
833 |
881 for (int i = 0; i < num; i++) { |
834 for (int i = 0; i < num_archivable_static_fields; i++) { |
882 ArchivableStaticFieldInfo* info = &fields[i]; |
835 ArchivableStaticFieldInfo* info = &archivable_static_fields[i]; |
|
836 TempNewSymbol klass_name = SymbolTable::new_symbol(info->klass_name, THREAD); |
883 TempNewSymbol klass_name = SymbolTable::new_symbol(info->klass_name, THREAD); |
837 TempNewSymbol field_name = SymbolTable::new_symbol(info->field_name, THREAD); |
884 TempNewSymbol field_name = SymbolTable::new_symbol(info->field_name, THREAD); |
838 |
885 |
839 Klass* k = SystemDictionary::resolve_or_null(klass_name, THREAD); |
886 Klass* k = SystemDictionary::resolve_or_null(klass_name, THREAD); |
840 assert(k != NULL && !HAS_PENDING_EXCEPTION, "class must exist"); |
887 assert(k != NULL && !HAS_PENDING_EXCEPTION, "class must exist"); |
847 info->klass = ik; |
894 info->klass = ik; |
848 info->offset = finder.offset(); |
895 info->offset = finder.offset(); |
849 } |
896 } |
850 } |
897 } |
851 |
898 |
852 void HeapShared::archive_object_subgraphs(Thread* THREAD) { |
899 void HeapShared::init_subgraph_entry_fields(Thread* THREAD) { |
|
900 _dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable(); |
|
901 |
|
902 init_subgraph_entry_fields(closed_archive_subgraph_entry_fields, |
|
903 num_closed_archive_subgraph_entry_fields, |
|
904 THREAD); |
|
905 init_subgraph_entry_fields(open_archive_subgraph_entry_fields, |
|
906 num_open_archive_subgraph_entry_fields, |
|
907 THREAD); |
|
908 } |
|
909 |
|
910 void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], |
|
911 int num, bool is_closed_archive, |
|
912 Thread* THREAD) { |
|
913 _num_total_subgraph_recordings = 0; |
|
914 _num_total_walked_objs = 0; |
|
915 _num_total_archived_objs = 0; |
|
916 _num_total_recorded_klasses = 0; |
|
917 _num_total_verifications = 0; |
|
918 |
853 // For each class X that has one or more archived fields: |
919 // For each class X that has one or more archived fields: |
854 // [1] Dump the subgraph of each archived field |
920 // [1] Dump the subgraph of each archived field |
855 // [2] Create a list of all the class of the objects that can be reached |
921 // [2] Create a list of all the class of the objects that can be reached |
856 // by any of these static fields. |
922 // by any of these static fields. |
857 // At runtime, these classes are initialized before X's archived fields |
923 // At runtime, these classes are initialized before X's archived fields |
858 // are restored by HeapShared::initialize_from_archived_subgraph(). |
924 // are restored by HeapShared::initialize_from_archived_subgraph(). |
859 int i; |
925 int i; |
860 for (i = 0; i < num_archivable_static_fields; ) { |
926 for (i = 0; i < num; ) { |
861 ArchivableStaticFieldInfo* info = &archivable_static_fields[i]; |
927 ArchivableStaticFieldInfo* info = &fields[i]; |
862 const char* klass_name = info->klass_name; |
928 const char* klass_name = info->klass_name; |
863 start_recording_subgraph(info->klass, klass_name); |
929 start_recording_subgraph(info->klass, klass_name); |
864 |
930 |
865 // If you have specified consecutive fields of the same klass in |
931 // If you have specified consecutive fields of the same klass in |
866 // archivable_static_fields[], these will be archived in the same |
932 // fields[], these will be archived in the same |
867 // {start_recording_subgraph ... done_recording_subgraph} pass to |
933 // {start_recording_subgraph ... done_recording_subgraph} pass to |
868 // save time. |
934 // save time. |
869 for (; i < num_archivable_static_fields; i++) { |
935 for (; i < num; i++) { |
870 ArchivableStaticFieldInfo* f = &archivable_static_fields[i]; |
936 ArchivableStaticFieldInfo* f = &fields[i]; |
871 if (f->klass_name != klass_name) { |
937 if (f->klass_name != klass_name) { |
872 break; |
938 break; |
873 } |
939 } |
874 archive_reachable_objects_from_static_field(f->klass, f->klass_name, |
940 archive_reachable_objects_from_static_field(f->klass, f->klass_name, |
875 f->offset, f->field_name, CHECK); |
941 f->offset, f->field_name, |
|
942 is_closed_archive, CHECK); |
876 } |
943 } |
877 done_recording_subgraph(info->klass, klass_name); |
944 done_recording_subgraph(info->klass, klass_name); |
878 } |
945 } |
879 |
946 |
880 log_info(cds, heap)("Performed subgraph records = %d times", _num_total_subgraph_recordings); |
947 log_info(cds, heap)("Archived subgraph records in %s archive heap region = %d", |
881 log_info(cds, heap)("Walked %d objects", _num_total_walked_objs); |
948 is_closed_archive ? "closed" : "open", |
882 log_info(cds, heap)("Archived %d objects", _num_total_archived_objs); |
949 _num_total_subgraph_recordings); |
883 log_info(cds, heap)("Recorded %d klasses", _num_total_recorded_klasses); |
950 log_info(cds, heap)(" Walked %d objects", _num_total_walked_objs); |
884 |
951 log_info(cds, heap)(" Archived %d objects", _num_total_archived_objs); |
|
952 log_info(cds, heap)(" Recorded %d klasses", _num_total_recorded_klasses); |
885 |
953 |
886 #ifndef PRODUCT |
954 #ifndef PRODUCT |
887 for (int i = 0; i < num_archivable_static_fields; i++) { |
955 for (int i = 0; i < num; i++) { |
888 ArchivableStaticFieldInfo* f = &archivable_static_fields[i]; |
956 ArchivableStaticFieldInfo* f = &fields[i]; |
889 verify_subgraph_from_static_field(f->klass, f->offset); |
957 verify_subgraph_from_static_field(f->klass, f->offset); |
890 } |
958 } |
891 log_info(cds, heap)("Verified %d references", _num_total_verifications); |
959 log_info(cds, heap)(" Verified %d references", _num_total_verifications); |
892 #endif |
960 #endif |
893 } |
961 } |
894 |
962 |
895 // At dump-time, find the location of all the non-null oop pointers in an archived heap |
963 // At dump-time, find the location of all the non-null oop pointers in an archived heap |
896 // region. This way we can quickly relocate all the pointers without using |
964 // region. This way we can quickly relocate all the pointers without using |