< prev index next > src/hotspot/share/cds/archiveUtils.cpp
Print this page
#include "cds/dynamicArchive.hpp"
#include "cds/filemap.hpp"
#include "cds/heapShared.hpp"
#include "cds/lambdaProxyClassDictionary.hpp"
#include "cds/metaspaceShared.hpp"
+ #include "classfile/classLoader.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/vmClasses.hpp"
#include "interpreter/bootstrapInfo.hpp"
#include "memory/metaspaceUtils.hpp"
#include "memory/resourceArea.hpp"
#include "utilities/spinYield.hpp"
CHeapBitMap* ArchivePtrMarker::_ptrmap = nullptr;
CHeapBitMap* ArchivePtrMarker::_rw_ptrmap = nullptr;
CHeapBitMap* ArchivePtrMarker::_ro_ptrmap = nullptr;
+ CHeapBitMap* ArchivePtrMarker::_cc_ptrmap = nullptr;
VirtualSpace* ArchivePtrMarker::_vs;
bool ArchivePtrMarker::_compacted;
void ArchivePtrMarker::initialize(CHeapBitMap* ptrmap, VirtualSpace* vs) {
assert(_ptrmap == nullptr, "initialize only once");
assert(_rw_ptrmap == nullptr, "initialize only once");
assert(_ro_ptrmap == nullptr, "initialize only once");
+ assert(_cc_ptrmap == nullptr, "initialize only once");
_vs = vs;
_compacted = false;
_ptrmap = ptrmap;
// Use this as initial guesstimate. We should need less space in the
// We need one bit per pointer in the archive.
_ptrmap->initialize(estimated_archive_size / sizeof(intptr_t));
}
! void ArchivePtrMarker::initialize_rw_ro_maps(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap) {
address* buff_bottom = (address*)ArchiveBuilder::current()->buffer_bottom();
address* rw_bottom = (address*)ArchiveBuilder::current()->rw_region()->base();
address* ro_bottom = (address*)ArchiveBuilder::current()->ro_region()->base();
! // The bit in _ptrmap that cover the very first word in the rw/ro regions.
size_t rw_start = rw_bottom - buff_bottom;
size_t ro_start = ro_bottom - buff_bottom;
// The number of bits used by the rw/ro ptrmaps. We might have lots of zero
// bits at the bottom and top of rw/ro ptrmaps, but these zeros will be
// removed by FileMapInfo::write_bitmap_region().
size_t rw_size = ArchiveBuilder::current()->rw_region()->used() / sizeof(address);
size_t ro_size = ArchiveBuilder::current()->ro_region()->used() / sizeof(address);
// The last (exclusive) bit in _ptrmap that covers the rw/ro regions.
// Note: _ptrmap is dynamically expanded only when an actual pointer is written, so
// it may not be as large as we want.
size_t rw_end = MIN2<size_t>(rw_start + rw_size, _ptrmap->size());
size_t ro_end = MIN2<size_t>(ro_start + ro_size, _ptrmap->size());
rw_ptrmap->initialize(rw_size);
ro_ptrmap->initialize(ro_size);
for (size_t rw_bit = rw_start; rw_bit < rw_end; rw_bit++) {
rw_ptrmap->at_put(rw_bit - rw_start, _ptrmap->at(rw_bit));
}
for(size_t ro_bit = ro_start; ro_bit < ro_end; ro_bit++) {
ro_ptrmap->at_put(ro_bit - ro_start, _ptrmap->at(ro_bit));
}
_rw_ptrmap = rw_ptrmap;
_ro_ptrmap = ro_ptrmap;
}
void ArchivePtrMarker::mark_pointer(address* ptr_loc) {
assert(_ptrmap != nullptr, "not initialized");
assert(!_compacted, "cannot mark anymore");
// We need one bit per pointer in the archive.
_ptrmap->initialize(estimated_archive_size / sizeof(intptr_t));
}
! void ArchivePtrMarker::initialize_rw_ro_cc_maps(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap, CHeapBitMap* cc_ptrmap) {
address* buff_bottom = (address*)ArchiveBuilder::current()->buffer_bottom();
address* rw_bottom = (address*)ArchiveBuilder::current()->rw_region()->base();
address* ro_bottom = (address*)ArchiveBuilder::current()->ro_region()->base();
+ address* cc_bottom = (address*)ArchiveBuilder::current()->cc_region()->base();
! // The bit in _ptrmap that cover the very first word in the rw/ro/cc regions.
size_t rw_start = rw_bottom - buff_bottom;
size_t ro_start = ro_bottom - buff_bottom;
+ size_t cc_start = cc_bottom - buff_bottom;
// The number of bits used by the rw/ro ptrmaps. We might have lots of zero
// bits at the bottom and top of rw/ro ptrmaps, but these zeros will be
// removed by FileMapInfo::write_bitmap_region().
size_t rw_size = ArchiveBuilder::current()->rw_region()->used() / sizeof(address);
size_t ro_size = ArchiveBuilder::current()->ro_region()->used() / sizeof(address);
+ size_t cc_size = ArchiveBuilder::current()->cc_region()->used() / sizeof(address);
// The last (exclusive) bit in _ptrmap that covers the rw/ro regions.
// Note: _ptrmap is dynamically expanded only when an actual pointer is written, so
// it may not be as large as we want.
size_t rw_end = MIN2<size_t>(rw_start + rw_size, _ptrmap->size());
size_t ro_end = MIN2<size_t>(ro_start + ro_size, _ptrmap->size());
+ size_t cc_end = MIN2<size_t>(cc_start + cc_size, _ptrmap->size());
rw_ptrmap->initialize(rw_size);
ro_ptrmap->initialize(ro_size);
+ cc_ptrmap->initialize(cc_size);
for (size_t rw_bit = rw_start; rw_bit < rw_end; rw_bit++) {
rw_ptrmap->at_put(rw_bit - rw_start, _ptrmap->at(rw_bit));
}
for(size_t ro_bit = ro_start; ro_bit < ro_end; ro_bit++) {
ro_ptrmap->at_put(ro_bit - ro_start, _ptrmap->at(ro_bit));
}
+ for (size_t cc_bit = cc_start; cc_bit < cc_end; cc_bit++) {
+ cc_ptrmap->at_put(cc_bit - cc_start, _ptrmap->at(cc_bit));
+ }
+
_rw_ptrmap = rw_ptrmap;
_ro_ptrmap = ro_ptrmap;
+ _cc_ptrmap = cc_ptrmap;
}
void ArchivePtrMarker::mark_pointer(address* ptr_loc) {
assert(_ptrmap != nullptr, "not initialized");
assert(!_compacted, "cannot mark anymore");
ArchivePtrMarker::mark_pointer(p);
}
}
void DumpRegion::print(size_t total_bytes) const {
log_debug(cds)("%s space: %9zu [ %4.1f%% of total] out of %9zu bytes [%5.1f%% used] at " INTPTR_FORMAT,
_name, used(), percent_of(used(), total_bytes), reserved(), percent_of(used(), reserved()),
! p2i(ArchiveBuilder::current()->to_requested(_base)));
}
void DumpRegion::print_out_of_space_msg(const char* failing_region, size_t needed_bytes) {
log_error(cds)("[%-8s] " PTR_FORMAT " - " PTR_FORMAT " capacity =%9d, allocated =%9d",
_name, p2i(_base), p2i(_top), int(_end - _base), int(_top - _base));
ArchivePtrMarker::mark_pointer(p);
}
}
void DumpRegion::print(size_t total_bytes) const {
+ char* base = used() > 0 ? ArchiveBuilder::current()->to_requested(_base) : nullptr;
log_debug(cds)("%s space: %9zu [ %4.1f%% of total] out of %9zu bytes [%5.1f%% used] at " INTPTR_FORMAT,
_name, used(), percent_of(used(), total_bytes), reserved(), percent_of(used(), reserved()),
! p2i(base));
}
void DumpRegion::print_out_of_space_msg(const char* failing_region, size_t needed_bytes) {
log_error(cds)("[%-8s] " PTR_FORMAT " - " PTR_FORMAT " capacity =%9d, allocated =%9d",
_name, p2i(_base), p2i(_top), int(_end - _base), int(_top - _base));
_base = _top = _rs->base();
_end = _rs->end();
}
void DumpRegion::pack(DumpRegion* next) {
! assert(!is_packed(), "sanity");
! _end = (char*)align_up(_top, MetaspaceShared::core_region_alignment());
! _is_packed = true;
if (next != nullptr) {
next->_rs = _rs;
next->_vs = _vs;
next->_base = next->_top = this->_end;
next->_end = _rs->end();
_base = _top = _rs->base();
_end = _rs->end();
}
void DumpRegion::pack(DumpRegion* next) {
! if (!is_packed()) {
! _end = (char*)align_up(_top, MetaspaceShared::core_region_alignment());
! _is_packed = true;
+ }
if (next != nullptr) {
next->_rs = _rs;
next->_vs = _vs;
next->_base = next->_top = this->_end;
next->_end = _rs->end();
}
}
}
}
+
+ // "boot", "platform", "app" or nullptr
+ const char* ArchiveUtils::builtin_loader_name_or_null(oop loader) {
+ if (loader == nullptr) {
+ return "boot";
+ } else if (loader == SystemDictionary::java_platform_loader()) {
+ return "platform";
+ } else if (loader == SystemDictionary::java_system_loader()) {
+ return "app";
+ } else {
+ return nullptr;
+ }
+ }
+
+ // "boot", "platform", "app". Asserts if not a built-in-loader
+ const char* ArchiveUtils::builtin_loader_name(oop loader) {
+ const char* name = builtin_loader_name_or_null(loader);
+ assert(name != nullptr, "must be a built-in loader");
+ return name;
+ }
+
+ bool ArchiveUtils::builtin_loader_from_type(const char* loader_type, oop* value_ret) {
+ if (strcmp(loader_type, "boot") == 0) {
+ *value_ret = nullptr;
+ return true;
+ } else if (strcmp(loader_type, "platform") == 0) {
+ *value_ret = SystemDictionary::java_platform_loader();
+ return true;
+ } else if (strcmp(loader_type, "app") == 0) {
+ *value_ret = SystemDictionary::java_system_loader();
+ return true;
+ } else {
+ DEBUG_ONLY(*value_ret = cast_to_oop((void*)badOopVal));
+ return false;
+ }
+ }
+
+ oop ArchiveUtils::builtin_loader_from_type(int loader_type) {
+ if (loader_type == ClassLoader::BOOT_LOADER) {
+ return nullptr;
+ } else if (loader_type == ClassLoader::PLATFORM_LOADER) {
+ return SystemDictionary::java_platform_loader();
+ } else if (loader_type == ClassLoader::APP_LOADER) {
+ return SystemDictionary::java_system_loader();
+ } else {
+ ShouldNotReachHere();
+ return nullptr;
+ }
+ }
+
bool ArchiveUtils::has_aot_initialized_mirror(InstanceKlass* src_ik) {
if (SystemDictionaryShared::is_excluded_class(src_ik)) {
assert(!ArchiveBuilder::current()->has_been_buffered(src_ik), "sanity");
return false;
}
< prev index next >