15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "cds/aotArtifactFinder.hpp"
26 #include "cds/aotClassLinker.hpp"
27 #include "cds/aotLinkedClassBulkLoader.hpp"
28 #include "cds/archiveBuilder.hpp"
29 #include "cds/archiveHeapWriter.hpp"
30 #include "cds/archiveUtils.hpp"
31 #include "cds/cdsConfig.hpp"
32 #include "cds/cppVtables.hpp"
33 #include "cds/dumpAllocStats.hpp"
34 #include "cds/dynamicArchive.hpp"
35 #include "cds/heapShared.hpp"
36 #include "cds/metaspaceShared.hpp"
37 #include "cds/regeneratedClasses.hpp"
38 #include "classfile/classLoader.hpp"
39 #include "classfile/classLoaderDataShared.hpp"
40 #include "classfile/classLoaderExt.hpp"
41 #include "classfile/javaClasses.hpp"
42 #include "classfile/symbolTable.hpp"
43 #include "classfile/systemDictionaryShared.hpp"
44 #include "classfile/vmClasses.hpp"
45 #include "interpreter/abstractInterpreter.hpp"
46 #include "jvm.h"
47 #include "logging/log.hpp"
48 #include "logging/logStream.hpp"
49 #include "memory/allStatic.hpp"
50 #include "memory/memoryReserver.hpp"
51 #include "memory/memRegion.hpp"
52 #include "memory/resourceArea.hpp"
53 #include "oops/compressedKlass.inline.hpp"
54 #include "oops/instanceKlass.hpp"
55 #include "oops/objArrayKlass.hpp"
56 #include "oops/objArrayOop.inline.hpp"
57 #include "oops/oopHandle.inline.hpp"
58 #include "runtime/arguments.hpp"
59 #include "runtime/fieldDescriptor.inline.hpp"
60 #include "runtime/globals_extension.hpp"
61 #include "runtime/javaThread.hpp"
62 #include "runtime/sharedRuntime.hpp"
63 #include "utilities/align.hpp"
64 #include "utilities/bitMap.inline.hpp"
65 #include "utilities/formatBuffer.hpp"
66
67 ArchiveBuilder* ArchiveBuilder::_current = nullptr;
68
69 ArchiveBuilder::OtherROAllocMark::~OtherROAllocMark() {
70 char* newtop = ArchiveBuilder::current()->_ro_region.top();
71 ArchiveBuilder::alloc_stats()->record_other_type(int(newtop - _oldtop), true);
72 }
73
74 ArchiveBuilder::SourceObjList::SourceObjList() : _ptrmap(16 * K, mtClassShared) {
75 _total_bytes = 0;
76 _objs = new (mtClassShared) GrowableArray<SourceObjInfo*>(128 * K, mtClassShared);
77 }
146 BitMap::idx_t start = BitMap::idx_t(src_info->ptrmap_start()); // inclusive
147 BitMap::idx_t end = BitMap::idx_t(src_info->ptrmap_end()); // exclusive
148
149 RelocateEmbeddedPointers relocator(builder, src_info->buffered_addr(), start);
150 _ptrmap.iterate(&relocator, start, end);
151 }
152
153 ArchiveBuilder::ArchiveBuilder() :
154 _current_dump_region(nullptr),
155 _buffer_bottom(nullptr),
156 _num_dump_regions_used(0),
157 _requested_static_archive_bottom(nullptr),
158 _requested_static_archive_top(nullptr),
159 _requested_dynamic_archive_bottom(nullptr),
160 _requested_dynamic_archive_top(nullptr),
161 _mapped_static_archive_bottom(nullptr),
162 _mapped_static_archive_top(nullptr),
163 _buffer_to_requested_delta(0),
164 _rw_region("rw", MAX_SHARED_DELTA),
165 _ro_region("ro", MAX_SHARED_DELTA),
166 _ptrmap(mtClassShared),
167 _rw_ptrmap(mtClassShared),
168 _ro_ptrmap(mtClassShared),
169 _rw_src_objs(),
170 _ro_src_objs(),
171 _src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
172 _buffered_to_src_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
173 _total_heap_region_size(0)
174 {
175 _klasses = new (mtClassShared) GrowableArray<Klass*>(4 * K, mtClassShared);
176 _symbols = new (mtClassShared) GrowableArray<Symbol*>(256 * K, mtClassShared);
177 _entropy_seed = 0x12345678;
178 assert(_current == nullptr, "must be");
179 _current = this;
180 }
181
182 ArchiveBuilder::~ArchiveBuilder() {
183 assert(_current == this, "must be");
184 _current = nullptr;
185
186 for (int i = 0; i < _symbols->length(); i++) {
187 _symbols->at(i)->decrement_refcount();
188 }
289
290 int ArchiveBuilder::compare_symbols_by_address(Symbol** a, Symbol** b) {
291 if (a[0] < b[0]) {
292 return -1;
293 } else {
294 assert(a[0] > b[0], "Duplicated symbol %s unexpected", (*a)->as_C_string());
295 return 1;
296 }
297 }
298
299 int ArchiveBuilder::compare_klass_by_name(Klass** a, Klass** b) {
300 return a[0]->name()->fast_compare(b[0]->name());
301 }
302
303 void ArchiveBuilder::sort_klasses() {
304 log_info(cds)("Sorting classes ... ");
305 _klasses->sort(compare_klass_by_name);
306 }
307
308 address ArchiveBuilder::reserve_buffer() {
309 size_t buffer_size = LP64_ONLY(CompressedClassSpaceSize) NOT_LP64(256 * M);
310 ReservedSpace rs = MemoryReserver::reserve(buffer_size,
311 MetaspaceShared::core_region_alignment(),
312 os::vm_page_size());
313 if (!rs.is_reserved()) {
314 log_error(cds)("Failed to reserve %zu bytes of output buffer.", buffer_size);
315 MetaspaceShared::unrecoverable_writing_error();
316 }
317
318 // buffer_bottom is the lowest address of the 2 core regions (rw, ro) when
319 // we are copying the class metadata into the buffer.
320 address buffer_bottom = (address)rs.base();
321 log_info(cds)("Reserved output buffer space at " PTR_FORMAT " [%zu bytes]",
322 p2i(buffer_bottom), buffer_size);
323 _shared_rs = rs;
324
325 _buffer_bottom = buffer_bottom;
326 _current_dump_region = &_rw_region;
327 _num_dump_regions_used = 1;
328 _current_dump_region->init(&_shared_rs, &_shared_vs);
329
507 return SystemDictionaryShared::is_excluded_class(ik);
508 } else if (klass->is_objArray_klass()) {
509 Klass* bottom = ObjArrayKlass::cast(klass)->bottom_klass();
510 if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_shared_static(bottom)) {
511 // The bottom class is in the static archive so it's clearly not excluded.
512 return false;
513 } else if (bottom->is_instance_klass()) {
514 return SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(bottom));
515 }
516 }
517
518 return false;
519 }
520
521 ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref *ref) {
522 address obj = ref->obj();
523 if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_in_shared_metaspace(obj)) {
524 // Don't dump existing shared metadata again.
525 return point_to_it;
526 } else if (ref->msotype() == MetaspaceObj::MethodDataType ||
527 ref->msotype() == MetaspaceObj::MethodCountersType) {
528 return set_to_null;
529 } else {
530 if (ref->msotype() == MetaspaceObj::ClassType) {
531 Klass* klass = (Klass*)ref->obj();
532 assert(klass->is_klass(), "must be");
533 if (is_excluded(klass)) {
534 ResourceMark rm;
535 log_debug(cds, dynamic)("Skipping class (excluded): %s", klass->external_name());
536 return set_to_null;
537 }
538 }
539
540 return make_a_copy;
541 }
542 }
543
544 void ArchiveBuilder::start_dump_region(DumpRegion* next) {
545 current_dump_region()->pack(next);
546 _current_dump_region = next;
547 _num_dump_regions_used ++;
548 }
701 }
702
703 bool ArchiveBuilder::has_been_buffered(address src_addr) const {
704 if (RegeneratedClasses::has_been_regenerated(src_addr) ||
705 _src_obj_table.get(src_addr) == nullptr ||
706 get_buffered_addr(src_addr) == nullptr) {
707 return false;
708 } else {
709 return true;
710 }
711 }
712
713 address ArchiveBuilder::get_buffered_addr(address src_addr) const {
714 SourceObjInfo* p = _src_obj_table.get(src_addr);
715 assert(p != nullptr, "src_addr " INTPTR_FORMAT " is used but has not been archived",
716 p2i(src_addr));
717
718 return p->buffered_addr();
719 }
720
721 address ArchiveBuilder::get_source_addr(address buffered_addr) const {
722 assert(is_in_buffer_space(buffered_addr), "must be");
723 address* src_p = _buffered_to_src_table.get(buffered_addr);
724 assert(src_p != nullptr && *src_p != nullptr, "must be");
725 return *src_p;
726 }
727
728 void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* src_objs) {
729 for (int i = 0; i < src_objs->objs()->length(); i++) {
730 src_objs->relocate(i, this);
731 }
732 }
733
734 void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() {
735 log_info(cds)("Relocating embedded pointers in core regions ... ");
736 relocate_embedded_pointers(&_rw_src_objs);
737 relocate_embedded_pointers(&_ro_src_objs);
738 }
739
740 #define ADD_COUNT(x) \
914 log_info(cds)(" boot " STATS_FORMAT, STATS_PARAMS(boot_klasses));
915 log_info(cds)(" vm " STATS_FORMAT, STATS_PARAMS(vm_klasses));
916 log_info(cds)(" platform " STATS_FORMAT, STATS_PARAMS(platform_klasses));
917 log_info(cds)(" app " STATS_FORMAT, STATS_PARAMS(app_klasses));
918 log_info(cds)(" unregistered " STATS_FORMAT, STATS_PARAMS(unregistered_klasses));
919 log_info(cds)(" (enum) " STATS_FORMAT, STATS_PARAMS(enum_klasses));
920 log_info(cds)(" (hidden) " STATS_FORMAT, STATS_PARAMS(hidden_klasses));
921 log_info(cds)(" (old) " STATS_FORMAT, STATS_PARAMS(old_klasses));
922 log_info(cds)(" (unlinked) = %5d, boot = %d, plat = %d, app = %d, unreg = %d",
923 num_unlinked_klasses, boot_unlinked, platform_unlinked, app_unlinked, unreg_unlinked);
924 log_info(cds)(" obj array classes = %5d", num_obj_array_klasses);
925 log_info(cds)(" type array classes = %5d", num_type_array_klasses);
926 log_info(cds)(" symbols = %5d", _symbols->length());
927
928 #undef STATS_FORMAT
929 #undef STATS_PARAMS
930
931 DynamicArchive::make_array_klasses_shareable();
932 }
933
934 void ArchiveBuilder::serialize_dynamic_archivable_items(SerializeClosure* soc) {
935 SymbolTable::serialize_shared_table_header(soc, false);
936 SystemDictionaryShared::serialize_dictionary_headers(soc, false);
937 DynamicArchive::serialize_array_klasses(soc);
938 AOTLinkedClassBulkLoader::serialize(soc, false);
939 }
940
941 uintx ArchiveBuilder::buffer_to_offset(address p) const {
942 address requested_p = to_requested(p);
943 assert(requested_p >= _requested_static_archive_bottom, "must be");
944 return requested_p - _requested_static_archive_bottom;
945 }
946
947 uintx ArchiveBuilder::any_to_offset(address p) const {
948 if (is_in_mapped_static_archive(p)) {
949 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
950 return p - _mapped_static_archive_bottom;
951 }
952 if (!is_in_buffer_space(p)) {
953 // p must be a "source" address
954 p = get_buffered_addr(p);
955 }
956 return buffer_to_offset(p);
957 }
958
959 address ArchiveBuilder::offset_to_buffered_address(u4 offset) const {
960 address requested_addr = _requested_static_archive_bottom + offset;
961 address buffered_addr = requested_addr - _buffer_to_requested_delta;
962 assert(is_in_buffer_space(buffered_addr), "bad offset");
963 return buffered_addr;
964 }
965
966 #if INCLUDE_CDS_JAVA_HEAP
967 narrowKlass ArchiveBuilder::get_requested_narrow_klass(Klass* k) {
968 assert(CDSConfig::is_dumping_heap(), "sanity");
969 k = get_buffered_klass(k);
970 Klass* requested_k = to_requested(k);
971 const int narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift();
972 #ifdef ASSERT
973 const size_t klass_alignment = MAX2(SharedSpaceObjectAlignment, (size_t)nth_bit(narrow_klass_shift));
974 assert(is_aligned(k, klass_alignment), "Klass " PTR_FORMAT " misaligned.", p2i(k));
975 #endif
976 address narrow_klass_base = _requested_static_archive_bottom; // runtime encoding base == runtime mapping start
977 // Note: use the "raw" version of encode that takes explicit narrow klass base and shift. Don't use any
978 // of the variants that do sanity checks, nor any of those that use the current - dump - JVM's encoding setting.
1055 ArchivePtrMarker::compact(_max_non_null_offset);
1056 }
1057 };
1058
1059 #ifdef _LP64
1060 int ArchiveBuilder::precomputed_narrow_klass_shift() {
1061 // Legacy Mode:
1062 // We use 32 bits for narrowKlass, which should cover the full 4G Klass range. Shift can be 0.
1063 // CompactObjectHeader Mode:
1064 // narrowKlass is much smaller, and we use the highest possible shift value to later get the maximum
1065 // Klass encoding range.
1066 //
1067 // Note that all of this may change in the future, if we decide to correct the pre-calculated
1068 // narrow Klass IDs at archive load time.
1069 assert(UseCompressedClassPointers, "Only needed for compressed class pointers");
1070 return UseCompactObjectHeaders ? CompressedKlassPointers::max_shift() : 0;
1071 }
1072 #endif // _LP64
1073
1074 void ArchiveBuilder::relocate_to_requested() {
1075 ro_region()->pack();
1076
1077 size_t my_archive_size = buffer_top() - buffer_bottom();
1078
1079 if (CDSConfig::is_dumping_static_archive()) {
1080 _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size;
1081 RelocateBufferToRequested<true> patcher(this);
1082 patcher.doit();
1083 } else {
1084 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
1085 _requested_dynamic_archive_top = _requested_dynamic_archive_bottom + my_archive_size;
1086 RelocateBufferToRequested<false> patcher(this);
1087 patcher.doit();
1088 }
1089 }
1090
1091 // Write detailed info to a mapfile to analyze contents of the archive.
1092 // static dump:
1093 // java -Xshare:dump -Xlog:cds+map=trace:file=cds.map:none:filesize=0
1094 // dynamic dump:
1095 // java -cp MyApp.jar -XX:ArchiveClassesAtExit=MyApp.jsa \
1377 assert(java_lang_Class::is_instance(scratch_mirror), "sanity");
1378 if (java_lang_Class::is_primitive(scratch_mirror)) {
1379 for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
1380 BasicType bt = (BasicType)i;
1381 if (!is_reference_type(bt) && scratch_mirror == HeapShared::scratch_java_mirror(bt)) {
1382 oop orig_mirror = Universe::java_mirror(bt);
1383 java_lang_Class::print_signature(orig_mirror, st);
1384 return;
1385 }
1386 }
1387 ShouldNotReachHere();
1388 }
1389 java_lang_Class::print_signature(scratch_mirror, st);
1390 }
1391
1392 static void log_heap_roots() {
1393 LogStreamHandle(Trace, cds, map, oops) st;
1394 if (st.is_enabled()) {
1395 for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
1396 st.print("roots[%4d]: ", i);
1397 print_oop_info_cr(&st, HeapShared::pending_roots()->at(i));
1398 }
1399 }
1400 }
1401
1402 // Example output:
1403 // - The first number is the requested address (if print_requested_addr == true)
1404 // - The second number is the narrowOop version of the requested address (if UseCompressedOops == true)
1405 // 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class Ljava/util/Array;
1406 // 0x00000007ffc000f8 (0xfff8001f) [B length: 11
1407 static void print_oop_info_cr(outputStream* st, oop source_oop, bool print_requested_addr = true) {
1408 if (source_oop == nullptr) {
1409 st->print_cr("null");
1410 } else {
1411 ResourceMark rm;
1412 oop requested_obj = ArchiveHeapWriter::source_obj_to_requested_obj(source_oop);
1413 if (print_requested_addr) {
1414 st->print(PTR_FORMAT " ", p2i(requested_obj));
1415 }
1416 if (UseCompressedOops) {
1417 st->print("(0x%08x) ", CompressedOops::narrow_oop_value(requested_obj));
1418 }
1419 if (source_oop->is_array()) {
1420 int array_len = arrayOop(source_oop)->length();
1421 st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
1422 } else {
1423 st->print("%s", source_oop->klass()->external_name());
1424
1425 if (java_lang_String::is_instance(source_oop)) {
1426 st->print(" ");
1427 java_lang_String::print(source_oop, st);
1428 } else if (java_lang_Class::is_instance(source_oop)) {
1429 oop scratch_mirror = source_oop;
1430
1431 st->print(" ");
1432 print_class_signature_for_mirror(st, scratch_mirror);
1433
1434 Klass* src_klass = java_lang_Class::as_Klass(scratch_mirror);
1435 if (src_klass != nullptr && src_klass->is_instance_klass()) {
1436 InstanceKlass* buffered_klass =
1437 ArchiveBuilder::current()->get_buffered_addr(InstanceKlass::cast(src_klass));
1438 if (buffered_klass->has_aot_initialized_mirror()) {
1439 st->print(" (aot-inited)");
1440 }
1441 }
1442 }
1443 st->cr();
1444 }
1445 }
1446 }
1447 #endif // INCLUDE_CDS_JAVA_HEAP
1496 if (heap_info->is_used()) {
1497 log_heap_region(heap_info);
1498 }
1499 #endif
1500
1501 log_info(cds, map)("[End of CDS archive map]");
1502 }
1503 }; // end ArchiveBuilder::CDSMapLogger
1504
1505 void ArchiveBuilder::print_stats() {
1506 _alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used()));
1507 }
1508
1509 void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, ArchiveHeapInfo* heap_info) {
1510 // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
1511 // MetaspaceShared::n_regions (internal to hotspot).
1512 assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
1513
1514 write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
1515 write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
1516
1517 // Split pointer map into read-write and read-only bitmaps
1518 ArchivePtrMarker::initialize_rw_ro_maps(&_rw_ptrmap, &_ro_ptrmap);
1519
1520 size_t bitmap_size_in_bytes;
1521 char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::rw_ptrmap(), ArchivePtrMarker::ro_ptrmap(), heap_info,
1522 bitmap_size_in_bytes);
1523
1524 if (heap_info->is_used()) {
1525 _total_heap_region_size = mapinfo->write_heap_region(heap_info);
1526 }
1527
1528 print_region_stats(mapinfo, heap_info);
1529
1530 mapinfo->set_requested_base((char*)MetaspaceShared::requested_base_address());
1531 mapinfo->set_header_crc(mapinfo->compute_header_crc());
1532 // After this point, we should not write any data into mapinfo->header() since this
1533 // would corrupt its checksum we have calculated before.
1534 mapinfo->write_header();
1535 mapinfo->close();
1536
1537 if (log_is_enabled(Info, cds)) {
1538 print_stats();
1539 }
1540
1541 if (log_is_enabled(Info, cds, map)) {
1547 }
1548
1549 void ArchiveBuilder::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) {
1550 mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec);
1551 }
1552
1553 void ArchiveBuilder::print_region_stats(FileMapInfo *mapinfo, ArchiveHeapInfo* heap_info) {
1554 // Print statistics of all the regions
1555 const size_t bitmap_used = mapinfo->region_at(MetaspaceShared::bm)->used();
1556 const size_t bitmap_reserved = mapinfo->region_at(MetaspaceShared::bm)->used_aligned();
1557 const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() +
1558 bitmap_reserved +
1559 _total_heap_region_size;
1560 const size_t total_bytes = _ro_region.used() + _rw_region.used() +
1561 bitmap_used +
1562 _total_heap_region_size;
1563 const double total_u_perc = percent_of(total_bytes, total_reserved);
1564
1565 _rw_region.print(total_reserved);
1566 _ro_region.print(total_reserved);
1567
1568 print_bitmap_region_stats(bitmap_used, total_reserved);
1569
1570 if (heap_info->is_used()) {
1571 print_heap_region_stats(heap_info, total_reserved);
1572 }
1573
1574 log_debug(cds)("total : %9zu [100.0%% of total] out of %9zu bytes [%5.1f%% used]",
1575 total_bytes, total_reserved, total_u_perc);
1576 }
1577
1578 void ArchiveBuilder::print_bitmap_region_stats(size_t size, size_t total_size) {
1579 log_debug(cds)("bm space: %9zu [ %4.1f%% of total] out of %9zu bytes [100.0%% used]",
1580 size, size/double(total_size)*100.0, size);
1581 }
1582
1583 void ArchiveBuilder::print_heap_region_stats(ArchiveHeapInfo *info, size_t total_size) {
1584 char* start = info->buffer_start();
1585 size_t size = info->buffer_byte_size();
1586 char* top = start + size;
|
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "cds/aotArtifactFinder.hpp"
26 #include "cds/aotClassLinker.hpp"
27 #include "cds/aotLinkedClassBulkLoader.hpp"
28 #include "cds/archiveBuilder.hpp"
29 #include "cds/archiveHeapWriter.hpp"
30 #include "cds/archiveUtils.hpp"
31 #include "cds/cdsConfig.hpp"
32 #include "cds/cppVtables.hpp"
33 #include "cds/dumpAllocStats.hpp"
34 #include "cds/dynamicArchive.hpp"
35 #include "cds/finalImageRecipes.hpp"
36 #include "cds/heapShared.hpp"
37 #include "cds/metaspaceShared.hpp"
38 #include "cds/regeneratedClasses.hpp"
39 #include "classfile/classLoader.hpp"
40 #include "classfile/classLoaderDataShared.hpp"
41 #include "classfile/classLoaderExt.hpp"
42 #include "classfile/javaClasses.hpp"
43 #include "classfile/symbolTable.hpp"
44 #include "classfile/systemDictionaryShared.hpp"
45 #include "classfile/vmClasses.hpp"
46 #include "code/SCCache.hpp"
47 #include "interpreter/abstractInterpreter.hpp"
48 #include "jvm.h"
49 #include "logging/log.hpp"
50 #include "logging/logStream.hpp"
51 #include "memory/allStatic.hpp"
52 #include "memory/memoryReserver.hpp"
53 #include "memory/memRegion.hpp"
54 #include "memory/resourceArea.hpp"
55 #include "oops/compressedKlass.inline.hpp"
56 #include "oops/instanceKlass.hpp"
57 #include "oops/methodCounters.hpp"
58 #include "oops/methodData.hpp"
59 #include "oops/objArrayKlass.hpp"
60 #include "oops/objArrayOop.inline.hpp"
61 #include "oops/oopHandle.inline.hpp"
62 #include "oops/trainingData.hpp"
63 #include "runtime/arguments.hpp"
64 #include "runtime/fieldDescriptor.inline.hpp"
65 #include "runtime/globals_extension.hpp"
66 #include "runtime/javaThread.hpp"
67 #include "runtime/sharedRuntime.hpp"
68 #include "utilities/align.hpp"
69 #include "utilities/bitMap.inline.hpp"
70 #include "utilities/formatBuffer.hpp"
71
72 ArchiveBuilder* ArchiveBuilder::_current = nullptr;
73
74 ArchiveBuilder::OtherROAllocMark::~OtherROAllocMark() {
75 char* newtop = ArchiveBuilder::current()->_ro_region.top();
76 ArchiveBuilder::alloc_stats()->record_other_type(int(newtop - _oldtop), true);
77 }
78
79 ArchiveBuilder::SourceObjList::SourceObjList() : _ptrmap(16 * K, mtClassShared) {
80 _total_bytes = 0;
81 _objs = new (mtClassShared) GrowableArray<SourceObjInfo*>(128 * K, mtClassShared);
82 }
151 BitMap::idx_t start = BitMap::idx_t(src_info->ptrmap_start()); // inclusive
152 BitMap::idx_t end = BitMap::idx_t(src_info->ptrmap_end()); // exclusive
153
154 RelocateEmbeddedPointers relocator(builder, src_info->buffered_addr(), start);
155 _ptrmap.iterate(&relocator, start, end);
156 }
157
158 ArchiveBuilder::ArchiveBuilder() :
159 _current_dump_region(nullptr),
160 _buffer_bottom(nullptr),
161 _num_dump_regions_used(0),
162 _requested_static_archive_bottom(nullptr),
163 _requested_static_archive_top(nullptr),
164 _requested_dynamic_archive_bottom(nullptr),
165 _requested_dynamic_archive_top(nullptr),
166 _mapped_static_archive_bottom(nullptr),
167 _mapped_static_archive_top(nullptr),
168 _buffer_to_requested_delta(0),
169 _rw_region("rw", MAX_SHARED_DELTA),
170 _ro_region("ro", MAX_SHARED_DELTA),
171 _cc_region("cc", MAX_SHARED_DELTA),
172 _ptrmap(mtClassShared),
173 _rw_ptrmap(mtClassShared),
174 _ro_ptrmap(mtClassShared),
175 _cc_ptrmap(mtClassShared),
176 _rw_src_objs(),
177 _ro_src_objs(),
178 _src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
179 _buffered_to_src_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
180 _total_heap_region_size(0)
181 {
182 _klasses = new (mtClassShared) GrowableArray<Klass*>(4 * K, mtClassShared);
183 _symbols = new (mtClassShared) GrowableArray<Symbol*>(256 * K, mtClassShared);
184 _entropy_seed = 0x12345678;
185 assert(_current == nullptr, "must be");
186 _current = this;
187 }
188
189 ArchiveBuilder::~ArchiveBuilder() {
190 assert(_current == this, "must be");
191 _current = nullptr;
192
193 for (int i = 0; i < _symbols->length(); i++) {
194 _symbols->at(i)->decrement_refcount();
195 }
296
297 int ArchiveBuilder::compare_symbols_by_address(Symbol** a, Symbol** b) {
298 if (a[0] < b[0]) {
299 return -1;
300 } else {
301 assert(a[0] > b[0], "Duplicated symbol %s unexpected", (*a)->as_C_string());
302 return 1;
303 }
304 }
305
306 int ArchiveBuilder::compare_klass_by_name(Klass** a, Klass** b) {
307 return a[0]->name()->fast_compare(b[0]->name());
308 }
309
310 void ArchiveBuilder::sort_klasses() {
311 log_info(cds)("Sorting classes ... ");
312 _klasses->sort(compare_klass_by_name);
313 }
314
315 address ArchiveBuilder::reserve_buffer() {
316 // SCCache::max_aot_code_size() accounts for cached code region.
317 size_t buffer_size = LP64_ONLY(CompressedClassSpaceSize) NOT_LP64(256 * M) + SCCache::max_aot_code_size();
318 ReservedSpace rs = MemoryReserver::reserve(buffer_size,
319 MetaspaceShared::core_region_alignment(),
320 os::vm_page_size());
321 if (!rs.is_reserved()) {
322 log_error(cds)("Failed to reserve %zu bytes of output buffer.", buffer_size);
323 MetaspaceShared::unrecoverable_writing_error();
324 }
325
326 // buffer_bottom is the lowest address of the 2 core regions (rw, ro) when
327 // we are copying the class metadata into the buffer.
328 address buffer_bottom = (address)rs.base();
329 log_info(cds)("Reserved output buffer space at " PTR_FORMAT " [%zu bytes]",
330 p2i(buffer_bottom), buffer_size);
331 _shared_rs = rs;
332
333 _buffer_bottom = buffer_bottom;
334 _current_dump_region = &_rw_region;
335 _num_dump_regions_used = 1;
336 _current_dump_region->init(&_shared_rs, &_shared_vs);
337
515 return SystemDictionaryShared::is_excluded_class(ik);
516 } else if (klass->is_objArray_klass()) {
517 Klass* bottom = ObjArrayKlass::cast(klass)->bottom_klass();
518 if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_shared_static(bottom)) {
519 // The bottom class is in the static archive so it's clearly not excluded.
520 return false;
521 } else if (bottom->is_instance_klass()) {
522 return SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(bottom));
523 }
524 }
525
526 return false;
527 }
528
529 ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref *ref) {
530 address obj = ref->obj();
531 if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_in_shared_metaspace(obj)) {
532 // Don't dump existing shared metadata again.
533 return point_to_it;
534 } else if (ref->msotype() == MetaspaceObj::MethodDataType ||
535 ref->msotype() == MetaspaceObj::MethodCountersType ||
536 ref->msotype() == MetaspaceObj::KlassTrainingDataType ||
537 ref->msotype() == MetaspaceObj::MethodTrainingDataType ||
538 ref->msotype() == MetaspaceObj::CompileTrainingDataType) {
539 return TrainingData::need_data() ? make_a_copy : set_to_null;
540 } else if (ref->msotype() == MetaspaceObj::AdapterHandlerEntryType) {
541 if (CDSConfig::is_dumping_adapters()) {
542 AdapterHandlerEntry* entry = (AdapterHandlerEntry*)ref->obj();
543 return AdapterHandlerLibrary::is_abstract_method_adapter(entry) ? set_to_null : make_a_copy;
544 } else {
545 return set_to_null;
546 }
547 } else {
548 if (ref->msotype() == MetaspaceObj::ClassType) {
549 Klass* klass = (Klass*)ref->obj();
550 assert(klass->is_klass(), "must be");
551 if (is_excluded(klass)) {
552 ResourceMark rm;
553 log_debug(cds, dynamic)("Skipping class (excluded): %s", klass->external_name());
554 return set_to_null;
555 }
556 }
557
558 return make_a_copy;
559 }
560 }
561
562 void ArchiveBuilder::start_dump_region(DumpRegion* next) {
563 current_dump_region()->pack(next);
564 _current_dump_region = next;
565 _num_dump_regions_used ++;
566 }
719 }
720
721 bool ArchiveBuilder::has_been_buffered(address src_addr) const {
722 if (RegeneratedClasses::has_been_regenerated(src_addr) ||
723 _src_obj_table.get(src_addr) == nullptr ||
724 get_buffered_addr(src_addr) == nullptr) {
725 return false;
726 } else {
727 return true;
728 }
729 }
730
731 address ArchiveBuilder::get_buffered_addr(address src_addr) const {
732 SourceObjInfo* p = _src_obj_table.get(src_addr);
733 assert(p != nullptr, "src_addr " INTPTR_FORMAT " is used but has not been archived",
734 p2i(src_addr));
735
736 return p->buffered_addr();
737 }
738
739 bool ArchiveBuilder::has_been_archived(address src_addr) const {
740 SourceObjInfo* p = _src_obj_table.get(src_addr);
741 return (p != nullptr);
742 }
743
744 address ArchiveBuilder::get_source_addr(address buffered_addr) const {
745 assert(is_in_buffer_space(buffered_addr), "must be");
746 address* src_p = _buffered_to_src_table.get(buffered_addr);
747 assert(src_p != nullptr && *src_p != nullptr, "must be");
748 return *src_p;
749 }
750
751 void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* src_objs) {
752 for (int i = 0; i < src_objs->objs()->length(); i++) {
753 src_objs->relocate(i, this);
754 }
755 }
756
757 void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() {
758 log_info(cds)("Relocating embedded pointers in core regions ... ");
759 relocate_embedded_pointers(&_rw_src_objs);
760 relocate_embedded_pointers(&_ro_src_objs);
761 }
762
763 #define ADD_COUNT(x) \
937 log_info(cds)(" boot " STATS_FORMAT, STATS_PARAMS(boot_klasses));
938 log_info(cds)(" vm " STATS_FORMAT, STATS_PARAMS(vm_klasses));
939 log_info(cds)(" platform " STATS_FORMAT, STATS_PARAMS(platform_klasses));
940 log_info(cds)(" app " STATS_FORMAT, STATS_PARAMS(app_klasses));
941 log_info(cds)(" unregistered " STATS_FORMAT, STATS_PARAMS(unregistered_klasses));
942 log_info(cds)(" (enum) " STATS_FORMAT, STATS_PARAMS(enum_klasses));
943 log_info(cds)(" (hidden) " STATS_FORMAT, STATS_PARAMS(hidden_klasses));
944 log_info(cds)(" (old) " STATS_FORMAT, STATS_PARAMS(old_klasses));
945 log_info(cds)(" (unlinked) = %5d, boot = %d, plat = %d, app = %d, unreg = %d",
946 num_unlinked_klasses, boot_unlinked, platform_unlinked, app_unlinked, unreg_unlinked);
947 log_info(cds)(" obj array classes = %5d", num_obj_array_klasses);
948 log_info(cds)(" type array classes = %5d", num_type_array_klasses);
949 log_info(cds)(" symbols = %5d", _symbols->length());
950
951 #undef STATS_FORMAT
952 #undef STATS_PARAMS
953
954 DynamicArchive::make_array_klasses_shareable();
955 }
956
957 void ArchiveBuilder::make_training_data_shareable() {
958 auto clean_td = [&] (address& src_obj, SourceObjInfo& info) {
959 if (!is_in_buffer_space(info.buffered_addr())) {
960 return;
961 }
962
963 if (info.msotype() == MetaspaceObj::KlassTrainingDataType ||
964 info.msotype() == MetaspaceObj::MethodTrainingDataType ||
965 info.msotype() == MetaspaceObj::CompileTrainingDataType) {
966 TrainingData* buffered_td = (TrainingData*)info.buffered_addr();
967 buffered_td->remove_unshareable_info();
968 } else if (info.msotype() == MetaspaceObj::MethodDataType) {
969 MethodData* buffered_mdo = (MethodData*)info.buffered_addr();
970 buffered_mdo->remove_unshareable_info();
971 } else if (info.msotype() == MetaspaceObj::MethodCountersType) {
972 MethodCounters* buffered_mc = (MethodCounters*)info.buffered_addr();
973 buffered_mc->remove_unshareable_info();
974 }
975 };
976 _src_obj_table.iterate_all(clean_td);
977 }
978
979 void ArchiveBuilder::serialize_dynamic_archivable_items(SerializeClosure* soc) {
980 SymbolTable::serialize_shared_table_header(soc, false);
981 SystemDictionaryShared::serialize_dictionary_headers(soc, false);
982 DynamicArchive::serialize_array_klasses(soc);
983 AOTLinkedClassBulkLoader::serialize(soc, false);
984 }
985
986 uintx ArchiveBuilder::buffer_to_offset(address p) const {
987 address requested_p = to_requested(p);
988 assert(requested_p >= _requested_static_archive_bottom, "must be");
989 return requested_p - _requested_static_archive_bottom;
990 }
991
992 uintx ArchiveBuilder::any_to_offset(address p) const {
993 if (is_in_mapped_static_archive(p)) {
994 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
995 return p - _mapped_static_archive_bottom;
996 }
997 if (!is_in_buffer_space(p)) {
998 // p must be a "source" address
999 p = get_buffered_addr(p);
1000 }
1001 return buffer_to_offset(p);
1002 }
1003
1004 void ArchiveBuilder::start_cc_region() {
1005 ro_region()->pack();
1006 start_dump_region(&_cc_region);
1007 }
1008
1009 void ArchiveBuilder::end_cc_region() {
1010 _cc_region.pack();
1011 }
1012
1013 address ArchiveBuilder::offset_to_buffered_address(u4 offset) const {
1014 address requested_addr = _requested_static_archive_bottom + offset;
1015 address buffered_addr = requested_addr - _buffer_to_requested_delta;
1016 assert(is_in_buffer_space(buffered_addr), "bad offset");
1017 return buffered_addr;
1018 }
1019
1020 #if INCLUDE_CDS_JAVA_HEAP
1021 narrowKlass ArchiveBuilder::get_requested_narrow_klass(Klass* k) {
1022 assert(CDSConfig::is_dumping_heap(), "sanity");
1023 k = get_buffered_klass(k);
1024 Klass* requested_k = to_requested(k);
1025 const int narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift();
1026 #ifdef ASSERT
1027 const size_t klass_alignment = MAX2(SharedSpaceObjectAlignment, (size_t)nth_bit(narrow_klass_shift));
1028 assert(is_aligned(k, klass_alignment), "Klass " PTR_FORMAT " misaligned.", p2i(k));
1029 #endif
1030 address narrow_klass_base = _requested_static_archive_bottom; // runtime encoding base == runtime mapping start
1031 // Note: use the "raw" version of encode that takes explicit narrow klass base and shift. Don't use any
1032 // of the variants that do sanity checks, nor any of those that use the current - dump - JVM's encoding setting.
1109 ArchivePtrMarker::compact(_max_non_null_offset);
1110 }
1111 };
1112
1113 #ifdef _LP64
1114 int ArchiveBuilder::precomputed_narrow_klass_shift() {
1115 // Legacy Mode:
1116 // We use 32 bits for narrowKlass, which should cover the full 4G Klass range. Shift can be 0.
1117 // CompactObjectHeader Mode:
1118 // narrowKlass is much smaller, and we use the highest possible shift value to later get the maximum
1119 // Klass encoding range.
1120 //
1121 // Note that all of this may change in the future, if we decide to correct the pre-calculated
1122 // narrow Klass IDs at archive load time.
1123 assert(UseCompressedClassPointers, "Only needed for compressed class pointers");
1124 return UseCompactObjectHeaders ? CompressedKlassPointers::max_shift() : 0;
1125 }
1126 #endif // _LP64
1127
1128 void ArchiveBuilder::relocate_to_requested() {
1129 if (!ro_region()->is_packed()) {
1130 ro_region()->pack();
1131 }
1132
1133 size_t my_archive_size = buffer_top() - buffer_bottom();
1134
1135 if (CDSConfig::is_dumping_static_archive()) {
1136 _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size;
1137 RelocateBufferToRequested<true> patcher(this);
1138 patcher.doit();
1139 } else {
1140 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
1141 _requested_dynamic_archive_top = _requested_dynamic_archive_bottom + my_archive_size;
1142 RelocateBufferToRequested<false> patcher(this);
1143 patcher.doit();
1144 }
1145 }
1146
1147 // Write detailed info to a mapfile to analyze contents of the archive.
1148 // static dump:
1149 // java -Xshare:dump -Xlog:cds+map=trace:file=cds.map:none:filesize=0
1150 // dynamic dump:
1151 // java -cp MyApp.jar -XX:ArchiveClassesAtExit=MyApp.jsa \
1433 assert(java_lang_Class::is_instance(scratch_mirror), "sanity");
1434 if (java_lang_Class::is_primitive(scratch_mirror)) {
1435 for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
1436 BasicType bt = (BasicType)i;
1437 if (!is_reference_type(bt) && scratch_mirror == HeapShared::scratch_java_mirror(bt)) {
1438 oop orig_mirror = Universe::java_mirror(bt);
1439 java_lang_Class::print_signature(orig_mirror, st);
1440 return;
1441 }
1442 }
1443 ShouldNotReachHere();
1444 }
1445 java_lang_Class::print_signature(scratch_mirror, st);
1446 }
1447
1448 static void log_heap_roots() {
1449 LogStreamHandle(Trace, cds, map, oops) st;
1450 if (st.is_enabled()) {
1451 for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
1452 st.print("roots[%4d]: ", i);
1453 print_oop_info_cr(&st, HeapShared::pending_roots()->at(i).resolve());
1454 }
1455 }
1456 }
1457
1458 // Example output:
1459 // - The first number is the requested address (if print_requested_addr == true)
1460 // - The second number is the narrowOop version of the requested address (if UseCompressedOops == true)
1461 // 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class Ljava/util/Array;
1462 // 0x00000007ffc000f8 (0xfff8001f) [B length: 11
1463 static void print_oop_info_cr(outputStream* st, oop source_oop, bool print_requested_addr = true) {
1464 if (source_oop == nullptr) {
1465 st->print_cr("null");
1466 } else {
1467 ResourceMark rm;
1468 oop requested_obj = ArchiveHeapWriter::source_obj_to_requested_obj(source_oop);
1469 if (print_requested_addr) {
1470 st->print(PTR_FORMAT " ", p2i(requested_obj));
1471 }
1472 if (UseCompressedOops) {
1473 st->print("(0x%08x) ", CompressedOops::narrow_oop_value(requested_obj));
1474 }
1475 if (source_oop->is_array()) {
1476 int array_len = arrayOop(source_oop)->length();
1477 st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
1478 } else {
1479 st->print("%s", source_oop->klass()->external_name());
1480
1481 if (java_lang_String::is_instance(source_oop)) {
1482 st->print(" ");
1483 java_lang_String::print(source_oop, st);
1484 } else if (java_lang_invoke_MethodType::is_instance(source_oop)) {
1485 st->print(" ");
1486 java_lang_invoke_MethodType::print_signature(source_oop, st);
1487 } else if (java_lang_Class::is_instance(source_oop)) {
1488 oop scratch_mirror = source_oop;
1489
1490 st->print(" ");
1491 print_class_signature_for_mirror(st, scratch_mirror);
1492
1493 Klass* src_klass = java_lang_Class::as_Klass(scratch_mirror);
1494 if (src_klass != nullptr && src_klass->is_instance_klass()) {
1495 InstanceKlass* buffered_klass =
1496 ArchiveBuilder::current()->get_buffered_addr(InstanceKlass::cast(src_klass));
1497 if (buffered_klass->has_aot_initialized_mirror()) {
1498 st->print(" (aot-inited)");
1499 }
1500 }
1501 }
1502 st->cr();
1503 }
1504 }
1505 }
1506 #endif // INCLUDE_CDS_JAVA_HEAP
1555 if (heap_info->is_used()) {
1556 log_heap_region(heap_info);
1557 }
1558 #endif
1559
1560 log_info(cds, map)("[End of CDS archive map]");
1561 }
1562 }; // end ArchiveBuilder::CDSMapLogger
1563
1564 void ArchiveBuilder::print_stats() {
1565 _alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used()));
1566 }
1567
1568 void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, ArchiveHeapInfo* heap_info) {
1569 // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
1570 // MetaspaceShared::n_regions (internal to hotspot).
1571 assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
1572
1573 write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
1574 write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
1575 write_region(mapinfo, MetaspaceShared::cc, &_cc_region, /*read_only=*/false,/*allow_exec=*/false);
1576
1577 // Split pointer map into read-write and read-only bitmaps
1578 ArchivePtrMarker::initialize_rw_ro_cc_maps(&_rw_ptrmap, &_ro_ptrmap, &_cc_ptrmap);
1579
1580 size_t bitmap_size_in_bytes;
1581 char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::rw_ptrmap(),
1582 ArchivePtrMarker::ro_ptrmap(),
1583 ArchivePtrMarker::cc_ptrmap(),
1584 heap_info,
1585 bitmap_size_in_bytes);
1586
1587 if (heap_info->is_used()) {
1588 _total_heap_region_size = mapinfo->write_heap_region(heap_info);
1589 }
1590
1591 print_region_stats(mapinfo, heap_info);
1592
1593 mapinfo->set_requested_base((char*)MetaspaceShared::requested_base_address());
1594 mapinfo->set_header_crc(mapinfo->compute_header_crc());
1595 // After this point, we should not write any data into mapinfo->header() since this
1596 // would corrupt its checksum we have calculated before.
1597 mapinfo->write_header();
1598 mapinfo->close();
1599
1600 if (log_is_enabled(Info, cds)) {
1601 print_stats();
1602 }
1603
1604 if (log_is_enabled(Info, cds, map)) {
1610 }
1611
1612 void ArchiveBuilder::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) {
1613 mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec);
1614 }
1615
1616 void ArchiveBuilder::print_region_stats(FileMapInfo *mapinfo, ArchiveHeapInfo* heap_info) {
1617 // Print statistics of all the regions
1618 const size_t bitmap_used = mapinfo->region_at(MetaspaceShared::bm)->used();
1619 const size_t bitmap_reserved = mapinfo->region_at(MetaspaceShared::bm)->used_aligned();
1620 const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() +
1621 bitmap_reserved +
1622 _total_heap_region_size;
1623 const size_t total_bytes = _ro_region.used() + _rw_region.used() +
1624 bitmap_used +
1625 _total_heap_region_size;
1626 const double total_u_perc = percent_of(total_bytes, total_reserved);
1627
1628 _rw_region.print(total_reserved);
1629 _ro_region.print(total_reserved);
1630 _cc_region.print(total_reserved);
1631
1632 print_bitmap_region_stats(bitmap_used, total_reserved);
1633
1634 if (heap_info->is_used()) {
1635 print_heap_region_stats(heap_info, total_reserved);
1636 }
1637
1638 log_debug(cds)("total : %9zu [100.0%% of total] out of %9zu bytes [%5.1f%% used]",
1639 total_bytes, total_reserved, total_u_perc);
1640 }
1641
1642 void ArchiveBuilder::print_bitmap_region_stats(size_t size, size_t total_size) {
1643 log_debug(cds)("bm space: %9zu [ %4.1f%% of total] out of %9zu bytes [100.0%% used]",
1644 size, size/double(total_size)*100.0, size);
1645 }
1646
1647 void ArchiveBuilder::print_heap_region_stats(ArchiveHeapInfo *info, size_t total_size) {
1648 char* start = info->buffer_start();
1649 size_t size = info->buffer_byte_size();
1650 char* top = start + size;
|