142
143 void AOTMappedHeapWriter::delete_tables_with_raw_oops() {
144 delete _source_objs;
145 _source_objs = nullptr;
146 }
147
148 void AOTMappedHeapWriter::add_source_obj(oop src_obj) {
149 _source_objs->append(src_obj);
150 }
151
152 void AOTMappedHeapWriter::write(GrowableArrayCHeap<oop, mtClassShared>* roots,
153 AOTMappedHeapInfo* heap_info) {
154 assert(CDSConfig::is_dumping_heap(), "sanity");
155 allocate_buffer();
156 copy_source_objs_to_buffer(roots);
157 set_requested_address_range(heap_info);
158 relocate_embedded_oops(roots, heap_info);
159 }
160
161 bool AOTMappedHeapWriter::is_too_large_to_archive(oop o) {
162 return is_too_large_to_archive(o->size());
163 }
164
165 bool AOTMappedHeapWriter::is_string_too_large_to_archive(oop string) {
166 typeArrayOop value = java_lang_String::value_no_keepalive(string);
167 return is_too_large_to_archive(value);
168 }
169
170 bool AOTMappedHeapWriter::is_too_large_to_archive(size_t size) {
171 assert(size > 0, "no zero-size object");
172 assert(size * HeapWordSize > size, "no overflow");
173 static_assert(MIN_GC_REGION_ALIGNMENT > 0, "must be positive");
174
175 size_t byte_size = size * HeapWordSize;
176 if (byte_size > size_t(MIN_GC_REGION_ALIGNMENT)) {
177 return true;
178 } else {
179 return false;
180 }
181 }
182
210 } else {
211 return nullptr;
212 }
213 }
214
215 Klass* AOTMappedHeapWriter::real_klass_of_buffered_oop(address buffered_addr) {
216 oop p = buffered_addr_to_source_obj(buffered_addr);
217 if (p != nullptr) {
218 return p->klass();
219 } else if (get_filler_size_at(buffered_addr) > 0) {
220 return Universe::fillerArrayKlass();
221 } else {
222 // This is one of the root segments
223 return Universe::objectArrayKlass();
224 }
225 }
226
227 size_t AOTMappedHeapWriter::size_of_buffered_oop(address buffered_addr) {
228 oop p = buffered_addr_to_source_obj(buffered_addr);
229 if (p != nullptr) {
230 return p->size();
231 }
232
233 size_t nbytes = get_filler_size_at(buffered_addr);
234 if (nbytes > 0) {
235 assert((nbytes % BytesPerWord) == 0, "should be aligned");
236 return nbytes / BytesPerWord;
237 }
238
239 address hrs = buffer_bottom();
240 for (size_t seg_idx = 0; seg_idx < _heap_root_segments.count(); seg_idx++) {
241 nbytes = _heap_root_segments.size_in_bytes(seg_idx);
242 if (hrs == buffered_addr) {
243 assert((nbytes % BytesPerWord) == 0, "should be aligned");
244 return nbytes / BytesPerWord;
245 }
246 hrs += nbytes;
247 }
248
249 ShouldNotReachHere();
516 void AOTMappedHeapWriter::update_stats(oop src_obj) {
517 if (java_lang_String::is_instance(src_obj)) {
518 _num_strings ++;
519 _string_bytes += src_obj->size() * HeapWordSize;
520 _string_bytes += java_lang_String::value(src_obj)->size() * HeapWordSize;
521 } else {
522 Klass* k = src_obj->klass();
523 Symbol* name = k->name();
524 if (name->equals("java/lang/NamedPackage") || name->equals("java/lang/Package")) {
525 _num_packages ++;
526 } else if (name->equals("java/security/ProtectionDomain")) {
527 _num_protection_domains ++;
528 }
529 }
530 }
531
532 size_t AOTMappedHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
533 update_stats(src_obj);
534
535 assert(!is_too_large_to_archive(src_obj), "already checked");
536 size_t byte_size = src_obj->size() * HeapWordSize;
537 assert(byte_size > 0, "no zero-size objects");
538
539 // For region-based collectors such as G1, the archive heap may be mapped into
540 // multiple regions. We need to make sure that we don't have an object that can possible
541 // span across two regions.
542 maybe_fill_gc_region_gap(byte_size);
543
544 size_t new_used = _buffer_used + byte_size;
545 assert(new_used > _buffer_used, "no wrap around");
546
547 size_t cur_min_region_bottom = align_down(_buffer_used, MIN_GC_REGION_ALIGNMENT);
548 size_t next_min_region_bottom = align_down(new_used, MIN_GC_REGION_ALIGNMENT);
549 assert(cur_min_region_bottom == next_min_region_bottom, "no object should cross minimal GC region boundaries");
550
551 ensure_buffer_space(new_used);
552
553 address from = cast_from_oop<address>(src_obj);
554 address to = offset_to_buffered_address<address>(_buffer_used);
555 assert(is_object_aligned(_buffer_used), "sanity");
556 assert(is_object_aligned(byte_size), "sanity");
557 memcpy(to, from, byte_size);
558
559 // These native pointers will be restored explicitly at run time.
560 if (java_lang_Module::is_instance(src_obj)) {
561 update_buffered_object_field<ModuleEntry*>(to, java_lang_Module::module_entry_offset(), nullptr);
562 } else if (java_lang_ClassLoader::is_instance(src_obj)) {
563 #ifdef ASSERT
564 // We only archive these loaders
565 if (src_obj != SystemDictionary::java_platform_loader() &&
566 src_obj != SystemDictionary::java_system_loader()) {
567 assert(src_obj->klass()->name()->equals("jdk/internal/loader/ClassLoaders$BootClassLoader"), "must be");
568 }
569 #endif
570 update_buffered_object_field<ClassLoaderData*>(to, java_lang_ClassLoader::loader_data_offset(), nullptr);
571 }
572
573 size_t buffered_obj_offset = _buffer_used;
574 _buffer_used = new_used;
575
576 return buffered_obj_offset;
577 }
712
713 assert(request_p >= (T*)_requested_bottom, "sanity");
714 assert(request_p < (T*)_requested_top, "sanity");
715 requested_region_bottom = _requested_bottom;
716
717 // Mark the pointer in the oopmap
718 T* region_bottom = (T*)requested_region_bottom;
719 assert(request_p >= region_bottom, "must be");
720 BitMap::idx_t idx = request_p - region_bottom;
721 assert(idx < oopmap->size(), "overflow");
722 oopmap->set_bit(idx);
723 }
724
725 void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop src_obj, Klass* src_klass) {
726 narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass);
727 address buffered_addr = requested_addr_to_buffered_addr(cast_from_oop<address>(requested_obj));
728
729 oop fake_oop = cast_to_oop(buffered_addr);
730 if (UseCompactObjectHeaders) {
731 fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk));
732 } else {
733 fake_oop->set_narrow_klass(nk);
734 }
735
736 if (src_obj == nullptr) {
737 return;
738 }
739 // We need to retain the identity_hash, because it may have been used by some hashtables
740 // in the shared heap.
741 if (!src_obj->fast_no_hash_check()) {
742 intptr_t src_hash = src_obj->identity_hash();
743 if (UseCompactObjectHeaders) {
744 fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk).copy_set_hash(src_hash));
745 } else {
746 fake_oop->set_mark(markWord::prototype().copy_set_hash(src_hash));
747 }
748 assert(fake_oop->mark().is_unlocked(), "sanity");
749
750 DEBUG_ONLY(intptr_t archived_hash = fake_oop->identity_hash());
751 assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash);
752 }
753 // Strip age bits.
754 fake_oop->set_mark(fake_oop->mark().set_age(0));
755 }
756
757 class AOTMappedHeapWriter::EmbeddedOopRelocator: public BasicOopIterateClosure {
758 oop _src_obj;
759 address _buffered_obj;
760 CHeapBitMap* _oopmap;
761 bool _is_java_lang_ref;
762 public:
763 EmbeddedOopRelocator(oop src_obj, address buffered_obj, CHeapBitMap* oopmap) :
764 _src_obj(src_obj), _buffered_obj(buffered_obj), _oopmap(oopmap)
765 {
766 _is_java_lang_ref = AOTReferenceObjSupport::check_if_ref_obj(src_obj);
767 }
768
769 void do_oop(narrowOop *p) { EmbeddedOopRelocator::do_oop_work(p); }
770 void do_oop( oop *p) { EmbeddedOopRelocator::do_oop_work(p); }
771
|
142
143 void AOTMappedHeapWriter::delete_tables_with_raw_oops() {
144 delete _source_objs;
145 _source_objs = nullptr;
146 }
147
148 void AOTMappedHeapWriter::add_source_obj(oop src_obj) {
149 _source_objs->append(src_obj);
150 }
151
152 void AOTMappedHeapWriter::write(GrowableArrayCHeap<oop, mtClassShared>* roots,
153 AOTMappedHeapInfo* heap_info) {
154 assert(CDSConfig::is_dumping_heap(), "sanity");
155 allocate_buffer();
156 copy_source_objs_to_buffer(roots);
157 set_requested_address_range(heap_info);
158 relocate_embedded_oops(roots, heap_info);
159 }
160
161 bool AOTMappedHeapWriter::is_too_large_to_archive(oop o) {
162 size_t size = o->size();
163 size = o->copy_size_cds(size, o->mark());
164 return is_too_large_to_archive(size);
165 }
166
167 bool AOTMappedHeapWriter::is_string_too_large_to_archive(oop string) {
168 typeArrayOop value = java_lang_String::value_no_keepalive(string);
169 return is_too_large_to_archive(value);
170 }
171
172 bool AOTMappedHeapWriter::is_too_large_to_archive(size_t size) {
173 assert(size > 0, "no zero-size object");
174 assert(size * HeapWordSize > size, "no overflow");
175 static_assert(MIN_GC_REGION_ALIGNMENT > 0, "must be positive");
176
177 size_t byte_size = size * HeapWordSize;
178 if (byte_size > size_t(MIN_GC_REGION_ALIGNMENT)) {
179 return true;
180 } else {
181 return false;
182 }
183 }
184
212 } else {
213 return nullptr;
214 }
215 }
216
217 Klass* AOTMappedHeapWriter::real_klass_of_buffered_oop(address buffered_addr) {
218 oop p = buffered_addr_to_source_obj(buffered_addr);
219 if (p != nullptr) {
220 return p->klass();
221 } else if (get_filler_size_at(buffered_addr) > 0) {
222 return Universe::fillerArrayKlass();
223 } else {
224 // This is one of the root segments
225 return Universe::objectArrayKlass();
226 }
227 }
228
229 size_t AOTMappedHeapWriter::size_of_buffered_oop(address buffered_addr) {
230 oop p = buffered_addr_to_source_obj(buffered_addr);
231 if (p != nullptr) {
232 if (UseCompactObjectHeaders) {
233 // Use the buffered object's mark word to determine size, not the source
234 // object's. The source object's mark word may have changed after the
235 // buffer was written (e.g., it may have been hashed by
236 // make_archived_object_cache_gc_safe), which would cause copy_size_cds
237 // to return a different size than what was actually allocated.
238 // The buffered copy's mark word was set by update_header_for_requested_obj
239 // and correctly reflects the allocated size via its expanded/hash state.
240 oop buffered_oop = cast_to_oop(buffered_addr);
241 markWord buffered_mark = buffered_oop->mark();
242 return buffered_oop->size_given_mark_and_klass(buffered_mark, p->klass());
243 }
244 return p->size();
245 }
246
247 size_t nbytes = get_filler_size_at(buffered_addr);
248 if (nbytes > 0) {
249 assert((nbytes % BytesPerWord) == 0, "should be aligned");
250 return nbytes / BytesPerWord;
251 }
252
253 address hrs = buffer_bottom();
254 for (size_t seg_idx = 0; seg_idx < _heap_root_segments.count(); seg_idx++) {
255 nbytes = _heap_root_segments.size_in_bytes(seg_idx);
256 if (hrs == buffered_addr) {
257 assert((nbytes % BytesPerWord) == 0, "should be aligned");
258 return nbytes / BytesPerWord;
259 }
260 hrs += nbytes;
261 }
262
263 ShouldNotReachHere();
530 void AOTMappedHeapWriter::update_stats(oop src_obj) {
531 if (java_lang_String::is_instance(src_obj)) {
532 _num_strings ++;
533 _string_bytes += src_obj->size() * HeapWordSize;
534 _string_bytes += java_lang_String::value(src_obj)->size() * HeapWordSize;
535 } else {
536 Klass* k = src_obj->klass();
537 Symbol* name = k->name();
538 if (name->equals("java/lang/NamedPackage") || name->equals("java/lang/Package")) {
539 _num_packages ++;
540 } else if (name->equals("java/security/ProtectionDomain")) {
541 _num_protection_domains ++;
542 }
543 }
544 }
545
546 size_t AOTMappedHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
547 update_stats(src_obj);
548
549 assert(!is_too_large_to_archive(src_obj), "already checked");
550 size_t old_size = src_obj->size();
551 size_t new_size = src_obj->copy_size_cds(old_size, src_obj->mark());
552 size_t byte_size = new_size * HeapWordSize;
553 assert(byte_size > 0, "no zero-size objects");
554
555 // For region-based collectors such as G1, the archive heap may be mapped into
556 // multiple regions. We need to make sure that we don't have an object that can possible
557 // span across two regions.
558 maybe_fill_gc_region_gap(byte_size);
559
560 size_t new_used = _buffer_used + byte_size;
561 assert(new_used > _buffer_used, "no wrap around");
562
563 size_t cur_min_region_bottom = align_down(_buffer_used, MIN_GC_REGION_ALIGNMENT);
564 size_t next_min_region_bottom = align_down(new_used, MIN_GC_REGION_ALIGNMENT);
565 assert(cur_min_region_bottom == next_min_region_bottom, "no object should cross minimal GC region boundaries");
566
567 ensure_buffer_space(new_used);
568
569 address from = cast_from_oop<address>(src_obj);
570 address to = offset_to_buffered_address<address>(_buffer_used);
571 assert(is_object_aligned(_buffer_used), "sanity");
572 assert(is_object_aligned(byte_size), "sanity");
573 memcpy(to, from, MIN2(new_size, old_size) * HeapWordSize);
574
575 // These native pointers will be restored explicitly at run time.
576 if (java_lang_Module::is_instance(src_obj)) {
577 update_buffered_object_field<ModuleEntry*>(to, java_lang_Module::module_entry_offset(), nullptr);
578 } else if (java_lang_ClassLoader::is_instance(src_obj)) {
579 #ifdef ASSERT
580 // We only archive these loaders
581 if (src_obj != SystemDictionary::java_platform_loader() &&
582 src_obj != SystemDictionary::java_system_loader()) {
583 assert(src_obj->klass()->name()->equals("jdk/internal/loader/ClassLoaders$BootClassLoader"), "must be");
584 }
585 #endif
586 update_buffered_object_field<ClassLoaderData*>(to, java_lang_ClassLoader::loader_data_offset(), nullptr);
587 }
588
589 size_t buffered_obj_offset = _buffer_used;
590 _buffer_used = new_used;
591
592 return buffered_obj_offset;
593 }
728
729 assert(request_p >= (T*)_requested_bottom, "sanity");
730 assert(request_p < (T*)_requested_top, "sanity");
731 requested_region_bottom = _requested_bottom;
732
733 // Mark the pointer in the oopmap
734 T* region_bottom = (T*)requested_region_bottom;
735 assert(request_p >= region_bottom, "must be");
736 BitMap::idx_t idx = request_p - region_bottom;
737 assert(idx < oopmap->size(), "overflow");
738 oopmap->set_bit(idx);
739 }
740
741 void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop src_obj, Klass* src_klass) {
742 narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass);
743 address buffered_addr = requested_addr_to_buffered_addr(cast_from_oop<address>(requested_obj));
744
745 oop fake_oop = cast_to_oop(buffered_addr);
746 if (UseCompactObjectHeaders) {
747 fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk));
748 assert(fake_oop->mark().narrow_klass() != 0, "must not be null");
749 } else {
750 fake_oop->set_narrow_klass(nk);
751 }
752
753 if (src_obj == nullptr) {
754 return;
755 }
756 // We need to retain the identity_hash, because it may have been used by some hashtables
757 // in the shared heap.
758 if (!src_obj->fast_no_hash_check()) {
759 intptr_t src_hash = src_obj->identity_hash();
760 if (UseCompactObjectHeaders) {
761 markWord m = markWord::prototype().set_narrow_klass(nk);
762 m = m.copy_hashctrl_from(src_obj->mark());
763 fake_oop->set_mark(m);
764 if (m.is_hashed_not_expanded()) {
765 fake_oop->set_mark(fake_oop->initialize_hash_if_necessary(src_obj, src_klass, m));
766 } else if (m.is_not_hashed_expanded()) {
767 fake_oop->set_mark(m.set_not_hashed_not_expanded());
768 }
769 assert(!fake_oop->mark().is_not_hashed_expanded() && !fake_oop->mark().is_hashed_not_expanded(), "must not be not-hashed-moved and not be hashed-not-moved");
770 } else {
771 fake_oop->set_mark(markWord::prototype().copy_set_hash(src_hash));
772 DEBUG_ONLY(intptr_t archived_hash = fake_oop->identity_hash());
773 assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash);
774 }
775 assert(fake_oop->mark().is_unlocked(), "sanity");
776 }
777 // Strip age bits.
778 fake_oop->set_mark(fake_oop->mark().set_age(0));
779 }
780
781 class AOTMappedHeapWriter::EmbeddedOopRelocator: public BasicOopIterateClosure {
782 oop _src_obj;
783 address _buffered_obj;
784 CHeapBitMap* _oopmap;
785 bool _is_java_lang_ref;
786 public:
787 EmbeddedOopRelocator(oop src_obj, address buffered_obj, CHeapBitMap* oopmap) :
788 _src_obj(src_obj), _buffered_obj(buffered_obj), _oopmap(oopmap)
789 {
790 _is_java_lang_ref = AOTReferenceObjSupport::check_if_ref_obj(src_obj);
791 }
792
793 void do_oop(narrowOop *p) { EmbeddedOopRelocator::do_oop_work(p); }
794 void do_oop( oop *p) { EmbeddedOopRelocator::do_oop_work(p); }
795
|