< prev index next > src/hotspot/share/cds/archiveHeapWriter.cpp
Print this page
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
#include "precompiled.hpp"
#include "cds/archiveHeapWriter.hpp"
#include "cds/cdsConfig.hpp"
#include "cds/filemap.hpp"
#include "cds/heapShared.hpp"
+ #include "cds/regeneratedClasses.hpp"
+ #include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.hpp"
HeapRootSegments ArchiveHeapWriter::_heap_root_segments;
address ArchiveHeapWriter::_requested_bottom;
address ArchiveHeapWriter::_requested_top;
+ static size_t _num_strings = 0;
+ static size_t _string_bytes = 0;
+ static size_t _num_packages = 0;
+ static size_t _num_protection_domains = 0;
+
GrowableArrayCHeap<ArchiveHeapWriter::NativePointerInfo, mtClassShared>* ArchiveHeapWriter::_native_pointers;
GrowableArrayCHeap<oop, mtClassShared>* ArchiveHeapWriter::_source_objs;
GrowableArrayCHeap<ArchiveHeapWriter::HeapObjOrder, mtClassShared>* ArchiveHeapWriter::_source_objs_order;
ArchiveHeapWriter::BufferOffsetToSourceObjectTable*
oop src_obj = _source_objs->at(src_obj_index);
HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(src_obj);
assert(info != nullptr, "must be");
size_t buffer_offset = copy_one_source_obj_to_buffer(src_obj);
info->set_buffer_offset(buffer_offset);
+ assert(buffer_offset <= 0x7fffffff, "sanity");
+ HeapShared::add_to_permanent_oop_table(src_obj, (int)buffer_offset);
_buffer_offset_to_source_obj_table->put_when_absent(buffer_offset, src_obj);
_buffer_offset_to_source_obj_table->maybe_grow();
}
log_info(cds)("Size of heap region = " SIZE_FORMAT " bytes, %d objects, %d roots, %d native ptrs",
_buffer_used, _source_objs->length() + 1, roots->length(), _num_native_ptrs);
+ log_info(cds)(" strings = " SIZE_FORMAT_W(8) " (" SIZE_FORMAT " bytes)", _num_strings, _string_bytes);
+ log_info(cds)(" packages = " SIZE_FORMAT_W(8), _num_packages);
+ log_info(cds)(" protection domains = " SIZE_FORMAT_W(8),_num_protection_domains);
}
size_t ArchiveHeapWriter::filler_array_byte_size(int length) {
size_t byte_size = objArrayOopDesc::object_size(length) * HeapWordSize;
return byte_size;
void update_buffered_object_field(address buffered_obj, int field_offset, T value) {
T* field_addr = cast_to_oop(buffered_obj)->field_addr<T>(field_offset);
*field_addr = value;
}
+ void ArchiveHeapWriter::update_stats(oop src_obj) {
+ if (java_lang_String::is_instance(src_obj)) {
+ _num_strings ++;
+ _string_bytes += src_obj->size() * HeapWordSize;
+ _string_bytes += java_lang_String::value(src_obj)->size() * HeapWordSize;
+ } else {
+ Klass* k = src_obj->klass();
+ Symbol* name = k->name();
+ if (name->equals("java/lang/NamedPackage") || name->equals("java/lang/Package")) {
+ _num_packages ++;
+ } else if (name->equals("java/security/ProtectionDomain")) {
+ _num_protection_domains ++;
+ }
+ }
+ }
+
size_t ArchiveHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
+ update_stats(src_obj);
+
assert(!is_too_large_to_archive(src_obj), "already checked");
size_t byte_size = src_obj->size() * HeapWordSize;
assert(byte_size > 0, "no zero-size objects");
// For region-based collectors such as G1, the archive heap may be mapped into
return CompressedOops::decode(*buffered_addr);
}
template <typename T> void ArchiveHeapWriter::relocate_field_in_buffer(T* field_addr_in_buffer, CHeapBitMap* oopmap) {
oop source_referent = load_source_oop_from_buffer<T>(field_addr_in_buffer);
- if (!CompressedOops::is_null(source_referent)) {
+ if (source_referent != nullptr) {
+ if (java_lang_Class::is_instance(source_referent)) {
+ source_referent = HeapShared::scratch_java_mirror(source_referent);
+ assert(source_referent != nullptr, "must be");
+ }
oop request_referent = source_obj_to_requested_obj(source_referent);
store_requested_oop_in_buffer<T>(field_addr_in_buffer, request_referent);
mark_oop_pointer<T>(field_addr_in_buffer, oopmap);
}
}
if (ptr != nullptr) {
NativePointerInfo info;
info._src_obj = src_obj;
info._field_offset = field_offset;
_native_pointers->append(info);
+ if (!ArchiveBuilder::current()->has_been_archived((address)ptr)) {
+ // Currently we supporting marking of only Method and Klass, both of which are
+ // subtypes of MetaData.
+ ResourceMark rm;
+ log_error(cds, heap)("Native pointer %p is not archived", ptr);
+ if (((Metadata*)ptr)->is_method()) {
+ log_error(cds, heap)("Method: %s", ((Method*)ptr)->external_name());
+ } else {
+ assert(((Metadata*)ptr)->is_klass(), "must be");
+ log_error(cds, heap)("Klass: %s", ((Klass*)ptr)->external_name());
+ }
+ HeapShared::exit_on_error();
+ }
HeapShared::set_has_native_pointers(src_obj);
_num_native_ptrs ++;
}
}
Metadata** buffered_field_addr = requested_addr_to_buffered_addr(requested_field_addr);
Metadata* native_ptr = *buffered_field_addr;
assert(native_ptr != nullptr, "sanity");
+ if (RegeneratedClasses::has_been_regenerated((address)native_ptr)) {
+ native_ptr = (Metadata*)RegeneratedClasses::get_regenerated_object((address)native_ptr);
+ }
+
address buffered_native_ptr = ArchiveBuilder::current()->get_buffered_addr((address)native_ptr);
address requested_native_ptr = ArchiveBuilder::current()->to_requested(buffered_native_ptr);
*buffered_field_addr = (Metadata*)requested_native_ptr;
}
< prev index next >