11/*
2- * Copyright (c) 2023 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2024 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -62,6 +62,7 @@ address ArchiveHeapWriter::_requested_top;
6262
6363GrowableArrayCHeap<ArchiveHeapWriter::NativePointerInfo, mtClassShared>* ArchiveHeapWriter::_native_pointers;
6464GrowableArrayCHeap<oop, mtClassShared>* ArchiveHeapWriter::_source_objs;
65+ GrowableArrayCHeap<int , mtClassShared>* ArchiveHeapWriter::_source_objs_order;
6566
6667ArchiveHeapWriter::BufferOffsetToSourceObjectTable*
6768 ArchiveHeapWriter::_buffer_offset_to_source_obj_table = nullptr ;
@@ -72,6 +73,7 @@ typedef ResourceHashtable<address, size_t,
7273 AnyObj::C_HEAP,
7374 mtClassShared> FillersTable;
7475static FillersTable* _fillers;
76+ static int _num_native_ptrs = 0 ;
7577
7678void ArchiveHeapWriter::init () {
7779 if (HeapShared::can_write ()) {
@@ -84,13 +86,15 @@ void ArchiveHeapWriter::init() {
8486
8587 _native_pointers = new GrowableArrayCHeap<NativePointerInfo, mtClassShared>(2048 );
8688 _source_objs = new GrowableArrayCHeap<oop, mtClassShared>(10000 );
89+ _source_objs_order = new GrowableArrayCHeap<int , mtClassShared>(10000 );
8790
8891 guarantee (UseG1GC, " implementation limitation" );
8992 guarantee (MIN_GC_REGION_ALIGNMENT <= /* G1*/ HeapRegion::min_region_size_in_words () * HeapWordSize, " must be" );
9093 }
9194}
9295
9396void ArchiveHeapWriter::add_source_obj (oop src_obj) {
97+ _source_objs_order->append (_source_objs->length ());
9498 _source_objs->append (src_obj);
9599}
96100
@@ -226,9 +230,54 @@ void ArchiveHeapWriter::copy_roots_to_buffer(GrowableArrayCHeap<oop, mtClassShar
226230 _buffer_used = new_used;
227231}
228232
233+ static int oop_sorting_rank (oop o) {
234+ bool has_o_ptr = HeapShared::has_oop_pointers (o);
235+ bool has_n_ptr = HeapShared::has_native_pointers (o);
236+
237+ if (!has_o_ptr) {
238+ if (!has_n_ptr) {
239+ return 0 ;
240+ } else {
241+ return 1 ;
242+ }
243+ } else {
244+ if (has_n_ptr) {
245+ return 2 ;
246+ } else {
247+ return 3 ;
248+ }
249+ }
250+ }
251+
252+ // The goal is to sort the objects in increasing order of:
253+ // - objects that have no pointers
254+ // - objects that have only native pointers
255+ // - objects that have both native and oop pointers
256+ // - objects that have only oop pointers
257+ int ArchiveHeapWriter::compare_objs_by_oop_fields (int * a, int * b) {
258+ oop oa = _source_objs->at (*a);
259+ oop ob = _source_objs->at (*b);
260+
261+ int rank_a = oop_sorting_rank (oa);
262+ int rank_b = oop_sorting_rank (ob);
263+
264+ if (rank_a != rank_b) {
265+ return rank_a - rank_b;
266+ } else {
267+ // If they are the same rank, sort them by their position in the _source_objs array
268+ return *a - *b;
269+ }
270+ }
271+
272+ void ArchiveHeapWriter::sort_source_objs () {
273+ _source_objs_order->sort (compare_objs_by_oop_fields);
274+ }
275+
229276void ArchiveHeapWriter::copy_source_objs_to_buffer (GrowableArrayCHeap<oop, mtClassShared>* roots) {
230- for (int i = 0 ; i < _source_objs->length (); i++) {
231- oop src_obj = _source_objs->at (i);
277+ sort_source_objs ();
278+ for (int i = 0 ; i < _source_objs_order->length (); i++) {
279+ int src_obj_index = _source_objs_order->at (i);
280+ oop src_obj = _source_objs->at (src_obj_index);
232281 HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache ()->get (src_obj);
233282 assert (info != nullptr , " must be" );
234283 size_t buffer_offset = copy_one_source_obj_to_buffer (src_obj);
@@ -239,8 +288,8 @@ void ArchiveHeapWriter::copy_source_objs_to_buffer(GrowableArrayCHeap<oop, mtCla
239288
240289 copy_roots_to_buffer (roots);
241290
242- log_info (cds)(" Size of heap region = " SIZE_FORMAT " bytes, %d objects, %d roots" ,
243- _buffer_used, _source_objs->length () + 1 , roots->length ());
291+ log_info (cds)(" Size of heap region = " SIZE_FORMAT " bytes, %d objects, %d roots, %d native ptrs " ,
292+ _buffer_used, _source_objs->length () + 1 , roots->length (), _num_native_ptrs );
244293}
245294
246295size_t ArchiveHeapWriter::filler_array_byte_size (int length) {
@@ -512,21 +561,35 @@ class ArchiveHeapWriter::EmbeddedOopRelocator: public BasicOopIterateClosure {
512561 }
513562};
514563
564+ static void log_bitmap_usage (const char * which, BitMap* bitmap, size_t total_bits) {
565+ // The whole heap is covered by total_bits, but there are only non-zero bits within [start ... end).
566+ size_t start = bitmap->find_first_set_bit (0 );
567+ size_t end = bitmap->size ();
568+ log_info (cds)(" %s = " SIZE_FORMAT_W (7 ) " ... " SIZE_FORMAT_W (7 ) " (%3zu%% ... %3zu%% = %3zu%%)" , which,
569+ start, end,
570+ start * 100 / total_bits,
571+ end * 100 / total_bits,
572+ (end - start) * 100 / total_bits);
573+ }
574+
515575// Update all oop fields embedded in the buffered objects
516576void ArchiveHeapWriter::relocate_embedded_oops (GrowableArrayCHeap<oop, mtClassShared>* roots,
517577 ArchiveHeapInfo* heap_info) {
518578 size_t oopmap_unit = (UseCompressedOops ? sizeof (narrowOop) : sizeof (oop));
519579 size_t heap_region_byte_size = _buffer_used;
520580 heap_info->oopmap ()->resize (heap_region_byte_size / oopmap_unit);
521581
522- auto iterator = [&] (oop src_obj, HeapShared::CachedOopInfo& info) {
523- oop requested_obj = requested_obj_from_buffer_offset (info.buffer_offset ());
582+ for (int i = 0 ; i < _source_objs_order->length (); i++) {
583+ int src_obj_index = _source_objs_order->at (i);
584+ oop src_obj = _source_objs->at (src_obj_index);
585+ HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache ()->get (src_obj);
586+ assert (info != nullptr , " must be" );
587+ oop requested_obj = requested_obj_from_buffer_offset (info->buffer_offset ());
524588 update_header_for_requested_obj (requested_obj, src_obj, src_obj->klass ());
525- address buffered_obj = offset_to_buffered_address<address>(info. buffer_offset ());
589+ address buffered_obj = offset_to_buffered_address<address>(info-> buffer_offset ());
526590 EmbeddedOopRelocator relocator (src_obj, buffered_obj, heap_info->oopmap ());
527591 src_obj->oop_iterate (&relocator);
528592 };
529- HeapShared::archived_object_cache ()->iterate_all (iterator);
530593
531594 // Relocate HeapShared::roots(), which is created in copy_roots_to_buffer() and
532595 // doesn't have a corresponding src_obj, so we can't use EmbeddedOopRelocator on it.
@@ -542,6 +605,10 @@ void ArchiveHeapWriter::relocate_embedded_oops(GrowableArrayCHeap<oop, mtClassSh
542605 }
543606
544607 compute_ptrmap (heap_info);
608+
609+ size_t total_bytes = (size_t )_buffer->length ();
610+ log_bitmap_usage (" oopmap" , heap_info->oopmap (), total_bytes / (UseCompressedOops ? sizeof (narrowOop) : sizeof (oop)));
611+ log_bitmap_usage (" ptrmap" , heap_info->ptrmap (), total_bytes / sizeof (address));
545612}
546613
547614void ArchiveHeapWriter::mark_native_pointer (oop src_obj, int field_offset) {
@@ -551,6 +618,8 @@ void ArchiveHeapWriter::mark_native_pointer(oop src_obj, int field_offset) {
551618 info._src_obj = src_obj;
552619 info._field_offset = field_offset;
553620 _native_pointers->append (info);
621+ HeapShared::set_has_native_pointers (src_obj);
622+ _num_native_ptrs ++;
554623 }
555624}
556625
@@ -565,6 +634,13 @@ bool ArchiveHeapWriter::is_marked_as_native_pointer(ArchiveHeapInfo* heap_info,
565634 assert ((Metadata**)_requested_bottom <= requested_field_addr && requested_field_addr < (Metadata**) _requested_top, " range check" );
566635
567636 BitMap::idx_t idx = requested_field_addr - (Metadata**) _requested_bottom;
637+ // Leading zeros have been removed so some addresses may not be in the ptrmap
638+ size_t start_pos = FileMapInfo::current_info ()->heap_ptrmap_start_pos ();
639+ if (idx < start_pos) {
640+ return false ;
641+ } else {
642+ idx -= start_pos;
643+ }
568644 return (idx < heap_info->ptrmap ()->size ()) && (heap_info->ptrmap ()->at (idx) == true );
569645}
570646
0 commit comments