Path: blob/master/src/hotspot/share/cds/archiveBuilder.hpp
41144 views
/*1* Copyright (c) 2020, 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#ifndef SHARE_CDS_ARCHIVEBUILDER_HPP25#define SHARE_CDS_ARCHIVEBUILDER_HPP2627#include "cds/archiveUtils.hpp"28#include "cds/dumpAllocStats.hpp"29#include "memory/metaspaceClosure.hpp"30#include "oops/array.hpp"31#include "oops/klass.hpp"32#include "runtime/os.hpp"33#include "utilities/bitMap.hpp"34#include "utilities/growableArray.hpp"35#include "utilities/hashtable.hpp"36#include "utilities/resourceHash.hpp"3738struct ArchiveHeapOopmapInfo;39class CHeapBitMap;40class FileMapInfo;41class Klass;42class MemRegion;43class Symbol;4445// Metaspace::allocate() requires that all blocks must be aligned with KlassAlignmentInBytes.46// We enforce the same alignment rule in blocks allocated from the shared space.47const int SharedSpaceObjectAlignment = KlassAlignmentInBytes;4849// Overview of CDS archive creation (for both static and dynamic dump):50//51// [1] Load all classes (static dump: from the classlist, dynamic dump: as part of app execution)52// [2] Allocate "output buffer"53// [3] Copy contents of the 2 "core" regions (rw/ro) into the output buffer.54// - allocate the cpp vtables in rw (static dump only)55// - memcpy the MetaspaceObjs into rw/ro:56// dump_rw_region();57// dump_ro_region();58// - fix all the pointers in the MetaspaceObjs to point to the copies59// relocate_metaspaceobj_embedded_pointers()60// [4] Copy symbol table, dictionary, etc, into the ro region61// [5] Relocate all the pointers in rw/ro, so that the archive can be mapped to62// the "requested" location without runtime relocation. See relocate_to_requested()63class ArchiveBuilder : public StackObj {64protected:65DumpRegion* _current_dump_space;66address _buffer_bottom; // for writing the contents of rw/ro regions67address _last_verified_top;68int _num_dump_regions_used;69size_t _other_region_used_bytes;7071// These are the addresses where we will request the static and dynamic archives to be72// mapped at run time. If the request fails (due to ASLR), we will map the archives at73// os-selected addresses.74address _requested_static_archive_bottom; // This is determined solely by the value of75// SharedBaseAddress during -Xshare:dump.76address _requested_static_archive_top;77address _requested_dynamic_archive_bottom; // Used only during dynamic dump. It's placed78// immediately above _requested_static_archive_top.79address _requested_dynamic_archive_top;8081// (Used only during dynamic dump) where the static archive is actually mapped. This82// may be different than _requested_static_archive_{bottom,top} due to ASLR83address _mapped_static_archive_bottom;84address _mapped_static_archive_top;8586intx _buffer_to_requested_delta;8788DumpRegion* current_dump_space() const { return _current_dump_space; }8990public:91enum FollowMode {92make_a_copy, point_to_it, set_to_null93};9495private:96class SpecialRefInfo {97// We have a "special pointer" of the given _type at _field_offset of _src_obj.98// See MetaspaceClosure::push_special().99MetaspaceClosure::SpecialRef _type;100address _src_obj;101size_t _field_offset;102103public:104SpecialRefInfo() {}105SpecialRefInfo(MetaspaceClosure::SpecialRef type, address src_obj, size_t field_offset)106: _type(type), _src_obj(src_obj), _field_offset(field_offset) {}107108MetaspaceClosure::SpecialRef type() const { return _type; }109address src_obj() const { return _src_obj; }110size_t field_offset() const { return _field_offset; }111};112113class SourceObjInfo {114MetaspaceClosure::Ref* _ref;115uintx _ptrmap_start; // The bit-offset of the start of this object (inclusive)116uintx _ptrmap_end; // The bit-offset of the end of this object (exclusive)117bool _read_only;118FollowMode _follow_mode;119int _size_in_bytes;120MetaspaceObj::Type _msotype;121address _dumped_addr; // Address this->obj(), as used by the dumped archive.122address _orig_obj; // The value of the original object (_ref->obj()) when this123// SourceObjInfo was created. Note that _ref->obj() may change124// later if _ref is relocated.125126public:127SourceObjInfo(MetaspaceClosure::Ref* ref, bool read_only, FollowMode follow_mode) :128_ref(ref), _ptrmap_start(0), _ptrmap_end(0), _read_only(read_only), _follow_mode(follow_mode),129_size_in_bytes(ref->size() * BytesPerWord), _msotype(ref->msotype()),130_orig_obj(ref->obj()) {131if (follow_mode == point_to_it) {132_dumped_addr = ref->obj();133} else {134_dumped_addr = NULL;135}136}137138bool should_copy() const { return _follow_mode == make_a_copy; }139MetaspaceClosure::Ref* ref() const { return _ref; }140void set_dumped_addr(address dumped_addr) {141assert(should_copy(), "must be");142assert(_dumped_addr == NULL, "cannot be copied twice");143assert(dumped_addr != NULL, "must be a valid copy");144_dumped_addr = dumped_addr;145}146void set_ptrmap_start(uintx v) { _ptrmap_start = v; }147void set_ptrmap_end(uintx v) { _ptrmap_end = v; }148uintx ptrmap_start() const { return _ptrmap_start; } // inclusive149uintx ptrmap_end() const { return _ptrmap_end; } // exclusive150bool read_only() const { return _read_only; }151int size_in_bytes() const { return _size_in_bytes; }152address orig_obj() const { return _orig_obj; }153address dumped_addr() const { return _dumped_addr; }154MetaspaceObj::Type msotype() const { return _msotype; }155156// convenience accessor157address obj() const { return ref()->obj(); }158};159160class SourceObjList {161uintx _total_bytes;162GrowableArray<SourceObjInfo*>* _objs; // Source objects to be archived163CHeapBitMap _ptrmap; // Marks the addresses of the pointer fields164// in the source objects165public:166SourceObjList();167~SourceObjList();168169GrowableArray<SourceObjInfo*>* objs() const { return _objs; }170171void append(MetaspaceClosure::Ref* enclosing_ref, SourceObjInfo* src_info);172void remember_embedded_pointer(SourceObjInfo* pointing_obj, MetaspaceClosure::Ref* ref);173void relocate(int i, ArchiveBuilder* builder);174175// convenience accessor176SourceObjInfo* at(int i) const { return objs()->at(i); }177};178179class SrcObjTableCleaner {180public:181bool do_entry(address key, const SourceObjInfo* value) {182delete value->ref();183return true;184}185};186187class CDSMapLogger;188189static const int INITIAL_TABLE_SIZE = 15889;190static const int MAX_TABLE_SIZE = 1000000;191192ReservedSpace _shared_rs;193VirtualSpace _shared_vs;194195DumpRegion _rw_region;196DumpRegion _ro_region;197CHeapBitMap _ptrmap; // bitmap used by ArchivePtrMarker198199SourceObjList _rw_src_objs; // objs to put in rw region200SourceObjList _ro_src_objs; // objs to put in ro region201KVHashtable<address, SourceObjInfo, mtClassShared> _src_obj_table;202GrowableArray<Klass*>* _klasses;203GrowableArray<Symbol*>* _symbols;204GrowableArray<SpecialRefInfo>* _special_refs;205206// statistics207int _num_instance_klasses;208int _num_obj_array_klasses;209int _num_type_array_klasses;210DumpAllocStats _alloc_stats;211size_t _total_closed_heap_region_size;212size_t _total_open_heap_region_size;213214void print_region_stats(FileMapInfo *map_info,215GrowableArray<MemRegion>* closed_heap_regions,216GrowableArray<MemRegion>* open_heap_regions);217void print_bitmap_region_stats(size_t size, size_t total_size);218void print_heap_region_stats(GrowableArray<MemRegion> *heap_mem,219const char *name, size_t total_size);220221// For global access.222static ArchiveBuilder* _current;223224public:225// Use this when you allocate space outside of ArchiveBuilder::dump_{rw,ro}_region.226// These are usually for misc tables that are allocated in the RO space.227class OtherROAllocMark {228char* _oldtop;229public:230OtherROAllocMark() {231_oldtop = _current->_ro_region.top();232}233~OtherROAllocMark();234};235236private:237bool is_dumping_full_module_graph();238FollowMode get_follow_mode(MetaspaceClosure::Ref *ref);239240void iterate_sorted_roots(MetaspaceClosure* it, bool is_relocating_pointers);241void sort_symbols_and_fix_hash();242void sort_klasses();243static int compare_symbols_by_address(Symbol** a, Symbol** b);244static int compare_klass_by_name(Klass** a, Klass** b);245246void make_shallow_copies(DumpRegion *dump_region, const SourceObjList* src_objs);247void make_shallow_copy(DumpRegion *dump_region, SourceObjInfo* src_info);248249void update_special_refs();250void relocate_embedded_pointers(SourceObjList* src_objs);251252bool is_excluded(Klass* k);253void clean_up_src_obj_table();254255protected:256virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) = 0;257258// Conservative estimate for number of bytes needed for:259size_t _estimated_metaspaceobj_bytes; // all archived MetaspaceObj's.260size_t _estimated_hashtable_bytes; // symbol table and dictionaries261262static const int _total_dump_regions = 2;263264size_t estimate_archive_size();265266void start_dump_space(DumpRegion* next);267void verify_estimate_size(size_t estimate, const char* which);268269public:270address reserve_buffer();271272address buffer_bottom() const { return _buffer_bottom; }273address buffer_top() const { return (address)current_dump_space()->top(); }274address requested_static_archive_bottom() const { return _requested_static_archive_bottom; }275address mapped_static_archive_bottom() const { return _mapped_static_archive_bottom; }276intx buffer_to_requested_delta() const { return _buffer_to_requested_delta; }277278bool is_in_buffer_space(address p) const {279return (buffer_bottom() <= p && p < buffer_top());280}281282template <typename T> bool is_in_requested_static_archive(T p) const {283return _requested_static_archive_bottom <= (address)p && (address)p < _requested_static_archive_top;284}285286template <typename T> bool is_in_mapped_static_archive(T p) const {287return _mapped_static_archive_bottom <= (address)p && (address)p < _mapped_static_archive_top;288}289290template <typename T> bool is_in_buffer_space(T obj) const {291return is_in_buffer_space(address(obj));292}293294template <typename T> T to_requested(T obj) const {295assert(is_in_buffer_space(obj), "must be");296return (T)(address(obj) + _buffer_to_requested_delta);297}298299static intx get_buffer_to_requested_delta() {300return current()->buffer_to_requested_delta();301}302303public:304static const uintx MAX_SHARED_DELTA = 0x7FFFFFFF;305306// The address p points to an object inside the output buffer. When the archive is mapped307// at the requested address, what's the offset of this object from _requested_static_archive_bottom?308uintx buffer_to_offset(address p) const;309310// Same as buffer_to_offset, except that the address p points to either (a) an object311// inside the output buffer, or (b), an object in the currently mapped static archive.312uintx any_to_offset(address p) const;313314template <typename T>315u4 buffer_to_offset_u4(T p) const {316uintx offset = buffer_to_offset((address)p);317guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset");318return (u4)offset;319}320321template <typename T>322u4 any_to_offset_u4(T p) const {323uintx offset = any_to_offset((address)p);324guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset");325return (u4)offset;326}327328static void assert_is_vm_thread() PRODUCT_RETURN;329330public:331ArchiveBuilder();332~ArchiveBuilder();333334void gather_klasses_and_symbols();335void gather_source_objs();336bool gather_klass_and_symbol(MetaspaceClosure::Ref* ref, bool read_only);337bool gather_one_source_obj(MetaspaceClosure::Ref* enclosing_ref, MetaspaceClosure::Ref* ref, bool read_only);338void add_special_ref(MetaspaceClosure::SpecialRef type, address src_obj, size_t field_offset);339void remember_embedded_pointer_in_copied_obj(MetaspaceClosure::Ref* enclosing_ref, MetaspaceClosure::Ref* ref);340341DumpRegion* rw_region() { return &_rw_region; }342DumpRegion* ro_region() { return &_ro_region; }343344static char* rw_region_alloc(size_t num_bytes) {345return current()->rw_region()->allocate(num_bytes);346}347static char* ro_region_alloc(size_t num_bytes) {348return current()->ro_region()->allocate(num_bytes);349}350351template <typename T>352static Array<T>* new_ro_array(int length) {353size_t byte_size = Array<T>::byte_sizeof(length, sizeof(T));354Array<T>* array = (Array<T>*)ro_region_alloc(byte_size);355array->initialize(length);356return array;357}358359template <typename T>360static Array<T>* new_rw_array(int length) {361size_t byte_size = Array<T>::byte_sizeof(length, sizeof(T));362Array<T>* array = (Array<T>*)rw_region_alloc(byte_size);363array->initialize(length);364return array;365}366367template <typename T>368static size_t ro_array_bytesize(int length) {369size_t byte_size = Array<T>::byte_sizeof(length, sizeof(T));370return align_up(byte_size, SharedSpaceObjectAlignment);371}372373void dump_rw_metadata();374void dump_ro_metadata();375void relocate_metaspaceobj_embedded_pointers();376void relocate_roots();377void relocate_vm_classes();378void make_klasses_shareable();379void relocate_to_requested();380void write_archive(FileMapInfo* mapinfo,381GrowableArray<MemRegion>* closed_heap_regions,382GrowableArray<MemRegion>* open_heap_regions,383GrowableArray<ArchiveHeapOopmapInfo>* closed_heap_oopmaps,384GrowableArray<ArchiveHeapOopmapInfo>* open_heap_oopmaps);385void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region,386bool read_only, bool allow_exec);387388address get_dumped_addr(address src_obj) const;389390// All klasses and symbols that will be copied into the archive391GrowableArray<Klass*>* klasses() const { return _klasses; }392GrowableArray<Symbol*>* symbols() const { return _symbols; }393394static bool is_active() {395return (_current != NULL);396}397398static ArchiveBuilder* current() {399assert_is_vm_thread();400assert(_current != NULL, "ArchiveBuilder must be active");401return _current;402}403404static DumpAllocStats* alloc_stats() {405return &(current()->_alloc_stats);406}407408static CompactHashtableStats* symbol_stats() {409return alloc_stats()->symbol_stats();410}411412static CompactHashtableStats* string_stats() {413return alloc_stats()->string_stats();414}415416void relocate_klass_ptr(oop o);417418static Klass* get_relocated_klass(Klass* orig_klass) {419Klass* klass = (Klass*)current()->get_dumped_addr((address)orig_klass);420assert(klass != NULL && klass->is_klass(), "must be");421return klass;422}423424static Symbol* get_relocated_symbol(Symbol* orig_symbol) {425return (Symbol*)current()->get_dumped_addr((address)orig_symbol);426}427428void print_stats();429void report_out_of_space(const char* name, size_t needed_bytes);430};431432#endif // SHARE_CDS_ARCHIVEBUILDER_HPP433434435