Path: blob/master/src/hotspot/share/cds/archiveUtils.cpp
41145 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "cds/archiveBuilder.hpp"26#include "cds/archiveUtils.hpp"27#include "cds/classListParser.hpp"28#include "cds/classListWriter.hpp"29#include "cds/dynamicArchive.hpp"30#include "cds/filemap.hpp"31#include "cds/heapShared.inline.hpp"32#include "cds/metaspaceShared.hpp"33#include "classfile/systemDictionaryShared.hpp"34#include "classfile/vmClasses.hpp"35#include "interpreter/bootstrapInfo.hpp"36#include "memory/metaspaceUtils.hpp"37#include "memory/resourceArea.hpp"38#include "oops/compressedOops.inline.hpp"39#include "runtime/arguments.hpp"40#include "utilities/bitMap.inline.hpp"4142CHeapBitMap* ArchivePtrMarker::_ptrmap = NULL;43VirtualSpace* ArchivePtrMarker::_vs;4445bool ArchivePtrMarker::_compacted;4647void ArchivePtrMarker::initialize(CHeapBitMap* ptrmap, VirtualSpace* vs) {48assert(_ptrmap == NULL, "initialize only once");49_vs = vs;50_compacted = false;51_ptrmap = ptrmap;5253// Use this as initial guesstimate. We should need less space in the54// archive, but if we're wrong the bitmap will be expanded automatically.55size_t estimated_archive_size = MetaspaceGC::capacity_until_GC();56// But set it smaller in debug builds so we always test the expansion code.57// (Default archive is about 12MB).58DEBUG_ONLY(estimated_archive_size = 6 * M);5960// We need one bit per pointer in the archive.61_ptrmap->initialize(estimated_archive_size / sizeof(intptr_t));62}6364void ArchivePtrMarker::mark_pointer(address* ptr_loc) {65assert(_ptrmap != NULL, "not initialized");66assert(!_compacted, "cannot mark anymore");6768if (ptr_base() <= ptr_loc && ptr_loc < ptr_end()) {69address value = *ptr_loc;70// We don't want any pointer that points to very bottom of the archive, otherwise when71// MetaspaceShared::default_base_address()==0, we can't distinguish between a pointer72// to nothing (NULL) vs a pointer to an objects that happens to be at the very bottom73// of the archive.74assert(value != (address)ptr_base(), "don't point to the bottom of the archive");7576if (value != NULL) {77assert(uintx(ptr_loc) % sizeof(intptr_t) == 0, "pointers must be stored in aligned addresses");78size_t idx = ptr_loc - ptr_base();79if (_ptrmap->size() <= idx) {80_ptrmap->resize((idx + 1) * 2);81}82assert(idx < _ptrmap->size(), "must be");83_ptrmap->set_bit(idx);84//tty->print_cr("Marking pointer [" PTR_FORMAT "] -> " PTR_FORMAT " @ " SIZE_FORMAT_W(5), p2i(ptr_loc), p2i(*ptr_loc), idx);85}86}87}8889void ArchivePtrMarker::clear_pointer(address* ptr_loc) {90assert(_ptrmap != NULL, "not initialized");91assert(!_compacted, "cannot clear anymore");9293assert(ptr_base() <= ptr_loc && ptr_loc < ptr_end(), "must be");94assert(uintx(ptr_loc) % sizeof(intptr_t) == 0, "pointers must be stored in aligned addresses");95size_t idx = ptr_loc - ptr_base();96assert(idx < _ptrmap->size(), "cannot clear pointers that have not been marked");97_ptrmap->clear_bit(idx);98//tty->print_cr("Clearing pointer [" PTR_FORMAT "] -> " PTR_FORMAT " @ " SIZE_FORMAT_W(5), p2i(ptr_loc), p2i(*ptr_loc), idx);99}100101class ArchivePtrBitmapCleaner: public BitMapClosure {102CHeapBitMap* _ptrmap;103address* _ptr_base;104address _relocatable_base;105address _relocatable_end;106size_t _max_non_null_offset;107108public:109ArchivePtrBitmapCleaner(CHeapBitMap* ptrmap, address* ptr_base, address relocatable_base, address relocatable_end) :110_ptrmap(ptrmap), _ptr_base(ptr_base),111_relocatable_base(relocatable_base), _relocatable_end(relocatable_end), _max_non_null_offset(0) {}112113bool do_bit(size_t offset) {114address* ptr_loc = _ptr_base + offset;115address ptr_value = *ptr_loc;116if (ptr_value != NULL) {117assert(_relocatable_base <= ptr_value && ptr_value < _relocatable_end, "do not point to arbitrary locations!");118if (_max_non_null_offset < offset) {119_max_non_null_offset = offset;120}121} else {122_ptrmap->clear_bit(offset);123DEBUG_ONLY(log_trace(cds, reloc)("Clearing pointer [" PTR_FORMAT "] -> NULL @ " SIZE_FORMAT_W(9), p2i(ptr_loc), offset));124}125126return true;127}128129size_t max_non_null_offset() const { return _max_non_null_offset; }130};131132void ArchivePtrMarker::compact(address relocatable_base, address relocatable_end) {133assert(!_compacted, "cannot compact again");134ArchivePtrBitmapCleaner cleaner(_ptrmap, ptr_base(), relocatable_base, relocatable_end);135_ptrmap->iterate(&cleaner);136compact(cleaner.max_non_null_offset());137}138139void ArchivePtrMarker::compact(size_t max_non_null_offset) {140assert(!_compacted, "cannot compact again");141_ptrmap->resize(max_non_null_offset + 1);142_compacted = true;143}144145char* DumpRegion::expand_top_to(char* newtop) {146assert(is_allocatable(), "must be initialized and not packed");147assert(newtop >= _top, "must not grow backwards");148if (newtop > _end) {149ArchiveBuilder::current()->report_out_of_space(_name, newtop - _top);150ShouldNotReachHere();151}152153commit_to(newtop);154_top = newtop;155156if (_max_delta > 0) {157uintx delta = ArchiveBuilder::current()->buffer_to_offset((address)(newtop-1));158if (delta > _max_delta) {159// This is just a sanity check and should not appear in any real world usage. This160// happens only if you allocate more than 2GB of shared objects and would require161// millions of shared classes.162vm_exit_during_initialization("Out of memory in the CDS archive",163"Please reduce the number of shared classes.");164}165}166167return _top;168}169170void DumpRegion::commit_to(char* newtop) {171Arguments::assert_is_dumping_archive();172char* base = _rs->base();173size_t need_committed_size = newtop - base;174size_t has_committed_size = _vs->committed_size();175if (need_committed_size < has_committed_size) {176return;177}178179size_t min_bytes = need_committed_size - has_committed_size;180size_t preferred_bytes = 1 * M;181size_t uncommitted = _vs->reserved_size() - has_committed_size;182183size_t commit = MAX2(min_bytes, preferred_bytes);184commit = MIN2(commit, uncommitted);185assert(commit <= uncommitted, "sanity");186187if (!_vs->expand_by(commit, false)) {188vm_exit_during_initialization(err_msg("Failed to expand shared space to " SIZE_FORMAT " bytes",189need_committed_size));190}191192const char* which;193if (_rs->base() == (char*)MetaspaceShared::symbol_rs_base()) {194which = "symbol";195} else {196which = "shared";197}198log_debug(cds)("Expanding %s spaces by " SIZE_FORMAT_W(7) " bytes [total " SIZE_FORMAT_W(9) " bytes ending at %p]",199which, commit, _vs->actual_committed_size(), _vs->high());200}201202203char* DumpRegion::allocate(size_t num_bytes) {204char* p = (char*)align_up(_top, (size_t)SharedSpaceObjectAlignment);205char* newtop = p + align_up(num_bytes, (size_t)SharedSpaceObjectAlignment);206expand_top_to(newtop);207memset(p, 0, newtop - p);208return p;209}210211void DumpRegion::append_intptr_t(intptr_t n, bool need_to_mark) {212assert(is_aligned(_top, sizeof(intptr_t)), "bad alignment");213intptr_t *p = (intptr_t*)_top;214char* newtop = _top + sizeof(intptr_t);215expand_top_to(newtop);216*p = n;217if (need_to_mark) {218ArchivePtrMarker::mark_pointer(p);219}220}221222void DumpRegion::print(size_t total_bytes) const {223log_debug(cds)("%-3s space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used] at " INTPTR_FORMAT,224_name, used(), percent_of(used(), total_bytes), reserved(), percent_of(used(), reserved()),225p2i(ArchiveBuilder::current()->to_requested(_base)));226}227228void DumpRegion::print_out_of_space_msg(const char* failing_region, size_t needed_bytes) {229log_error(cds)("[%-8s] " PTR_FORMAT " - " PTR_FORMAT " capacity =%9d, allocated =%9d",230_name, p2i(_base), p2i(_top), int(_end - _base), int(_top - _base));231if (strcmp(_name, failing_region) == 0) {232log_error(cds)(" required = %d", int(needed_bytes));233}234}235236void DumpRegion::init(ReservedSpace* rs, VirtualSpace* vs) {237_rs = rs;238_vs = vs;239// Start with 0 committed bytes. The memory will be committed as needed.240if (!_vs->initialize(*_rs, 0)) {241fatal("Unable to allocate memory for shared space");242}243_base = _top = _rs->base();244_end = _rs->end();245}246247void DumpRegion::pack(DumpRegion* next) {248assert(!is_packed(), "sanity");249_end = (char*)align_up(_top, MetaspaceShared::core_region_alignment());250_is_packed = true;251if (next != NULL) {252next->_rs = _rs;253next->_vs = _vs;254next->_base = next->_top = this->_end;255next->_end = _rs->end();256}257}258259void WriteClosure::do_oop(oop* o) {260if (*o == NULL) {261_dump_region->append_intptr_t(0);262} else {263assert(HeapShared::is_heap_object_archiving_allowed(),264"Archiving heap object is not allowed");265_dump_region->append_intptr_t(266(intptr_t)CompressedOops::encode_not_null(*o));267}268}269270void WriteClosure::do_region(u_char* start, size_t size) {271assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");272assert(size % sizeof(intptr_t) == 0, "bad size");273do_tag((int)size);274while (size > 0) {275_dump_region->append_intptr_t(*(intptr_t*)start, true);276start += sizeof(intptr_t);277size -= sizeof(intptr_t);278}279}280281void ReadClosure::do_ptr(void** p) {282assert(*p == NULL, "initializing previous initialized pointer.");283intptr_t obj = nextPtr();284assert((intptr_t)obj >= 0 || (intptr_t)obj < -100,285"hit tag while initializing ptrs.");286*p = (void*)obj;287}288289void ReadClosure::do_u4(u4* p) {290intptr_t obj = nextPtr();291*p = (u4)(uintx(obj));292}293294void ReadClosure::do_bool(bool* p) {295intptr_t obj = nextPtr();296*p = (bool)(uintx(obj));297}298299void ReadClosure::do_tag(int tag) {300int old_tag;301old_tag = (int)(intptr_t)nextPtr();302// do_int(&old_tag);303assert(tag == old_tag, "old tag doesn't match");304FileMapInfo::assert_mark(tag == old_tag);305}306307void ReadClosure::do_oop(oop *p) {308narrowOop o = CompressedOops::narrow_oop_cast(nextPtr());309if (CompressedOops::is_null(o) || !HeapShared::open_archive_heap_region_mapped()) {310*p = NULL;311} else {312assert(HeapShared::is_heap_object_archiving_allowed(),313"Archived heap object is not allowed");314assert(HeapShared::open_archive_heap_region_mapped(),315"Open archive heap region is not mapped");316*p = HeapShared::decode_from_archive(o);317}318}319320void ReadClosure::do_region(u_char* start, size_t size) {321assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");322assert(size % sizeof(intptr_t) == 0, "bad size");323do_tag((int)size);324while (size > 0) {325*(intptr_t*)start = nextPtr();326start += sizeof(intptr_t);327size -= sizeof(intptr_t);328}329}330331fileStream* ClassListWriter::_classlist_file = NULL;332333void ArchiveUtils::log_to_classlist(BootstrapInfo* bootstrap_specifier, TRAPS) {334if (ClassListWriter::is_enabled()) {335if (SystemDictionaryShared::is_supported_invokedynamic(bootstrap_specifier)) {336ResourceMark rm(THREAD);337const constantPoolHandle& pool = bootstrap_specifier->pool();338int pool_index = bootstrap_specifier->bss_index();339ClassListWriter w;340w.stream()->print("%s %s", LAMBDA_PROXY_TAG, pool->pool_holder()->name()->as_C_string());341CDSIndyInfo cii;342ClassListParser::populate_cds_indy_info(pool, pool_index, &cii, CHECK);343GrowableArray<const char*>* indy_items = cii.items();344for (int i = 0; i < indy_items->length(); i++) {345w.stream()->print(" %s", indy_items->at(i));346}347w.stream()->cr();348}349}350}351352353