Path: blob/master/src/hotspot/share/cds/heapShared.hpp
41144 views
/*1* Copyright (c) 2018, 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_HEAPSHARED_HPP25#define SHARE_CDS_HEAPSHARED_HPP2627#include "cds/metaspaceShared.hpp"28#include "classfile/compactHashtable.hpp"29#include "classfile/javaClasses.hpp"30#include "classfile/systemDictionary.hpp"31#include "gc/shared/gc_globals.hpp"32#include "memory/allocation.hpp"33#include "oops/compressedOops.hpp"34#include "oops/objArrayKlass.hpp"35#include "oops/oop.hpp"36#include "oops/oopHandle.hpp"37#include "oops/typeArrayKlass.hpp"38#include "utilities/bitMap.hpp"39#include "utilities/growableArray.hpp"40#include "utilities/resourceHash.hpp"4142#if INCLUDE_CDS_JAVA_HEAP43class DumpedInternedStrings;4445struct ArchivableStaticFieldInfo {46const char* klass_name;47const char* field_name;48InstanceKlass* klass;49int offset;50BasicType type;51};5253// A dump time sub-graph info for Klass _k. It includes the entry points54// (static fields in _k's mirror) of the archived sub-graphs reachable55// from _k's mirror. It also contains a list of Klasses of the objects56// within the sub-graphs.57class KlassSubGraphInfo: public CHeapObj<mtClass> {58private:59// The class that contains the static field(s) as the entry point(s)60// of archived object sub-graph(s).61Klass* _k;62// A list of classes need to be loaded and initialized before the archived63// object sub-graphs can be accessed at runtime.64GrowableArray<Klass*>* _subgraph_object_klasses;65// A list of _k's static fields as the entry points of archived sub-graphs.66// For each entry field, it is a tuple of field_offset, field_value and67// is_closed_archive flag.68GrowableArray<int>* _subgraph_entry_fields;6970// Does this KlassSubGraphInfo belong to the archived full module graph71bool _is_full_module_graph;7273// Does this KlassSubGraphInfo references any classes that were loaded while74// JvmtiExport::is_early_phase()!=true. If so, this KlassSubGraphInfo cannot be75// used at runtime if JVMTI ClassFileLoadHook is enabled.76bool _has_non_early_klasses;77static bool is_non_early_klass(Klass* k);7879public:80KlassSubGraphInfo(Klass* k, bool is_full_module_graph) :81_k(k), _subgraph_object_klasses(NULL),82_subgraph_entry_fields(NULL),83_is_full_module_graph(is_full_module_graph),84_has_non_early_klasses(false) {}8586~KlassSubGraphInfo() {87if (_subgraph_object_klasses != NULL) {88delete _subgraph_object_klasses;89}90if (_subgraph_entry_fields != NULL) {91delete _subgraph_entry_fields;92}93};9495Klass* klass() { return _k; }96GrowableArray<Klass*>* subgraph_object_klasses() {97return _subgraph_object_klasses;98}99GrowableArray<int>* subgraph_entry_fields() {100return _subgraph_entry_fields;101}102void add_subgraph_entry_field(int static_field_offset, oop v,103bool is_closed_archive);104void add_subgraph_object_klass(Klass *orig_k);105int num_subgraph_object_klasses() {106return _subgraph_object_klasses == NULL ? 0 :107_subgraph_object_klasses->length();108}109bool is_full_module_graph() const { return _is_full_module_graph; }110bool has_non_early_klasses() const { return _has_non_early_klasses; }111};112113// An archived record of object sub-graphs reachable from static114// fields within _k's mirror. The record is reloaded from the archive115// at runtime.116class ArchivedKlassSubGraphInfoRecord {117private:118Klass* _k;119bool _is_full_module_graph;120bool _has_non_early_klasses;121122// contains pairs of field offset and value for each subgraph entry field123Array<int>* _entry_field_records;124125// klasses of objects in archived sub-graphs referenced from the entry points126// (static fields) in the containing class127Array<Klass*>* _subgraph_object_klasses;128public:129ArchivedKlassSubGraphInfoRecord() :130_k(NULL), _entry_field_records(NULL), _subgraph_object_klasses(NULL) {}131void init(KlassSubGraphInfo* info);132Klass* klass() const { return _k; }133Array<int>* entry_field_records() const { return _entry_field_records; }134Array<Klass*>* subgraph_object_klasses() const { return _subgraph_object_klasses; }135bool is_full_module_graph() const { return _is_full_module_graph; }136bool has_non_early_klasses() const { return _has_non_early_klasses; }137};138#endif // INCLUDE_CDS_JAVA_HEAP139140class HeapShared: AllStatic {141friend class VerifySharedOopClosure;142private:143144#if INCLUDE_CDS_JAVA_HEAP145static bool _closed_archive_heap_region_mapped;146static bool _open_archive_heap_region_mapped;147static bool _archive_heap_region_fixed;148static DumpedInternedStrings *_dumped_interned_strings;149150public:151static bool oop_equals(oop const& p1, oop const& p2) {152return p1 == p2;153}154static unsigned oop_hash(oop const& p);155static unsigned string_oop_hash(oop const& string) {156return java_lang_String::hash_code(string);157}158159private:160typedef ResourceHashtable<oop, oop,161HeapShared::oop_hash,162HeapShared::oop_equals,16315889, // prime number164ResourceObj::C_HEAP> ArchivedObjectCache;165static ArchivedObjectCache* _archived_object_cache;166167static bool klass_equals(Klass* const& p1, Klass* const& p2) {168return primitive_equals<Klass*>(p1, p2);169}170171static unsigned klass_hash(Klass* const& klass) {172// Generate deterministic hashcode even if SharedBaseAddress is changed due to ASLR.173return primitive_hash<address>(address(klass) - SharedBaseAddress);174}175176class DumpTimeKlassSubGraphInfoTable177: public ResourceHashtable<Klass*, KlassSubGraphInfo,178HeapShared::klass_hash,179HeapShared::klass_equals,180137, // prime number181ResourceObj::C_HEAP> {182public:183int _count;184};185186public: // solaris compiler wants this for RunTimeKlassSubGraphInfoTable187inline static bool record_equals_compact_hashtable_entry(188const ArchivedKlassSubGraphInfoRecord* value, const Klass* key, int len_unused) {189return (value->klass() == key);190}191192private:193typedef OffsetCompactHashtable<194const Klass*,195const ArchivedKlassSubGraphInfoRecord*,196record_equals_compact_hashtable_entry197> RunTimeKlassSubGraphInfoTable;198199static DumpTimeKlassSubGraphInfoTable* _dump_time_subgraph_info_table;200static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table;201202static void check_closed_archive_heap_region_object(InstanceKlass* k);203204static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[],205int num,206bool is_closed_archive,207bool is_full_module_graph);208209// Archive object sub-graph starting from the given static field210// in Klass k's mirror.211static void archive_reachable_objects_from_static_field(212InstanceKlass* k, const char* klass_name,213int field_offset, const char* field_name,214bool is_closed_archive);215216static void verify_subgraph_from_static_field(217InstanceKlass* k, int field_offset) PRODUCT_RETURN;218static void verify_reachable_objects_from(oop obj, bool is_archived) PRODUCT_RETURN;219static void verify_subgraph_from(oop orig_obj) PRODUCT_RETURN;220221static KlassSubGraphInfo* init_subgraph_info(Klass *k, bool is_full_module_graph);222static KlassSubGraphInfo* get_subgraph_info(Klass *k);223224static void init_subgraph_entry_fields(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;225static void init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[],226int num, TRAPS);227228// Used by decode_from_archive229static address _narrow_oop_base;230static int _narrow_oop_shift;231232typedef ResourceHashtable<oop, bool,233HeapShared::oop_hash,234HeapShared::oop_equals,23515889, // prime number236ResourceObj::C_HEAP> SeenObjectsTable;237238static SeenObjectsTable *_seen_objects_table;239240static GrowableArrayCHeap<oop, mtClassShared>* _pending_roots;241static narrowOop _roots_narrow;242static OopHandle _roots;243244static void init_seen_objects_table() {245assert(_seen_objects_table == NULL, "must be");246_seen_objects_table = new (ResourceObj::C_HEAP, mtClass)SeenObjectsTable();247}248static void delete_seen_objects_table() {249assert(_seen_objects_table != NULL, "must be");250delete _seen_objects_table;251_seen_objects_table = NULL;252}253254// Statistics (for one round of start_recording_subgraph ... done_recording_subgraph)255static int _num_new_walked_objs;256static int _num_new_archived_objs;257static int _num_old_recorded_klasses;258259// Statistics (for all archived subgraphs)260static int _num_total_subgraph_recordings;261static int _num_total_walked_objs;262static int _num_total_archived_objs;263static int _num_total_recorded_klasses;264static int _num_total_verifications;265266static void start_recording_subgraph(InstanceKlass *k, const char* klass_name,267bool is_full_module_graph);268static void done_recording_subgraph(InstanceKlass *k, const char* klass_name);269270static bool has_been_seen_during_subgraph_recording(oop obj);271static void set_has_been_seen_during_subgraph_recording(oop obj);272273static void check_module_oop(oop orig_module_obj);274static void copy_roots();275276static void resolve_classes_for_subgraphs(ArchivableStaticFieldInfo fields[],277int num, JavaThread* THREAD);278static void resolve_classes_for_subgraph_of(Klass* k, JavaThread* THREAD);279static void clear_archived_roots_of(Klass* k);280static const ArchivedKlassSubGraphInfoRecord*281resolve_or_init_classes_for_subgraph_of(Klass* k, bool do_init, TRAPS);282static void resolve_or_init(Klass* k, bool do_init, TRAPS);283static void init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record);284public:285static void reset_archived_object_states(TRAPS);286static void create_archived_object_cache() {287_archived_object_cache =288new (ResourceObj::C_HEAP, mtClass)ArchivedObjectCache();289}290static void destroy_archived_object_cache() {291delete _archived_object_cache;292_archived_object_cache = NULL;293}294static ArchivedObjectCache* archived_object_cache() {295return _archived_object_cache;296}297298static oop find_archived_heap_object(oop obj);299static oop archive_heap_object(oop obj);300301static void archive_klass_objects();302303static void set_archive_heap_region_fixed() {304_archive_heap_region_fixed = true;305}306static bool archive_heap_region_fixed() {307return _archive_heap_region_fixed;308}309310static void archive_java_heap_objects(GrowableArray<MemRegion> *closed,311GrowableArray<MemRegion> *open);312static void copy_closed_archive_heap_objects(GrowableArray<MemRegion> * closed_archive);313static void copy_open_archive_heap_objects(GrowableArray<MemRegion> * open_archive);314315static oop archive_reachable_objects_from(int level,316KlassSubGraphInfo* subgraph_info,317oop orig_obj,318bool is_closed_archive);319320static ResourceBitMap calculate_oopmap(MemRegion region);321static void add_to_dumped_interned_strings(oop string);322323// We use the HeapShared::roots() array to make sure that objects stored in the324// archived heap regions are not prematurely collected. These roots include:325//326// - mirrors of classes that have not yet been loaded.327// - ConstantPool::resolved_references() of classes that have not yet been loaded.328// - ArchivedKlassSubGraphInfoRecords that have not been initialized329// - java.lang.Module objects that have not yet been added to the module graph330//331// When a mirror M becomes referenced by a newly loaded class K, M will be removed332// from HeapShared::roots() via clear_root(), and K will be responsible for333// keeping M alive.334//335// Other types of roots are also cleared similarly when they become referenced.336337// Dump-time only. Returns the index of the root, which can be used at run time to read338// the root using get_root(index, ...).339static int append_root(oop obj);340341// Dump-time and runtime342static objArrayOop roots();343static oop get_root(int index, bool clear=false);344345// Run-time only346static void set_roots(narrowOop roots);347static void clear_root(int index);348#endif // INCLUDE_CDS_JAVA_HEAP349350public:351static void run_full_gc_in_vm_thread() NOT_CDS_JAVA_HEAP_RETURN;352353static bool is_heap_object_archiving_allowed() {354CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);)355NOT_CDS_JAVA_HEAP(return false;)356}357358static bool is_heap_region(int idx) {359CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_closed_archive_heap_region &&360idx <= MetaspaceShared::last_open_archive_heap_region);)361NOT_CDS_JAVA_HEAP_RETURN_(false);362}363364static void set_closed_archive_heap_region_mapped() {365CDS_JAVA_HEAP_ONLY(_closed_archive_heap_region_mapped = true;)366NOT_CDS_JAVA_HEAP_RETURN;367}368static bool closed_archive_heap_region_mapped() {369CDS_JAVA_HEAP_ONLY(return _closed_archive_heap_region_mapped;)370NOT_CDS_JAVA_HEAP_RETURN_(false);371}372static void set_open_archive_heap_region_mapped() {373CDS_JAVA_HEAP_ONLY(_open_archive_heap_region_mapped = true;)374NOT_CDS_JAVA_HEAP_RETURN;375}376static bool open_archive_heap_region_mapped() {377CDS_JAVA_HEAP_ONLY(return _open_archive_heap_region_mapped;)378NOT_CDS_JAVA_HEAP_RETURN_(false);379}380static bool is_mapped() {381return closed_archive_heap_region_mapped() && open_archive_heap_region_mapped();382}383384static void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;385386inline static bool is_archived_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false);387388static void resolve_classes(JavaThread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;389static void initialize_from_archived_subgraph(Klass* k, JavaThread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;390391// NarrowOops stored in the CDS archive may use a different encoding scheme392// than CompressedOops::{base,shift} -- see FileMapInfo::map_heap_regions_impl.393// To decode them, do not use CompressedOops::decode_not_null. Use this394// function instead.395inline static oop decode_from_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL);396397static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN;398399static void patch_archived_heap_embedded_pointers(MemRegion mem, address oopmap,400size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN;401402static void init_for_dumping(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;403static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN;404static void serialize_subgraph_info_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;405};406407#if INCLUDE_CDS_JAVA_HEAP408class DumpedInternedStrings :409public ResourceHashtable<oop, bool,410HeapShared::string_oop_hash,411HeapShared::oop_equals,41215889, // prime number413ResourceObj::C_HEAP>414{};415#endif416417#endif // SHARE_CDS_HEAPSHARED_HPP418419420