1 /* 2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_MEMORY_HEAPSHARED_HPP 26 #define SHARE_MEMORY_HEAPSHARED_HPP 27 28 #include "classfile/compactHashtable.hpp" 29 #include "classfile/systemDictionary.hpp" 30 #include "memory/allocation.hpp" 31 #include "memory/metaspaceShared.hpp" 32 #include "oops/compressedOops.hpp" 33 #include "oops/objArrayKlass.hpp" 34 #include "oops/oop.hpp" 35 #include "oops/typeArrayKlass.hpp" 36 #include "utilities/bitMap.hpp" 37 #include "utilities/growableArray.hpp" 38 #include "utilities/resourceHash.hpp" 39 40 #if INCLUDE_CDS_JAVA_HEAP 41 struct ArchivableStaticFieldInfo { 42 const char* klass_name; 43 const char* field_name; 44 InstanceKlass* klass; 45 int offset; 46 BasicType type; 47 }; 48 49 // A dump time sub-graph info for Klass _k. It includes the entry points 50 // (static fields in _k's mirror) of the archived sub-graphs reachable 51 // from _k's mirror. It also contains a list of Klasses of the objects 52 // within the sub-graphs. 53 class KlassSubGraphInfo: public CHeapObj<mtClass> { 54 private: 55 // The class that contains the static field(s) as the entry point(s) 56 // of archived object sub-graph(s). 57 Klass* _k; 58 // A list of classes need to be loaded and initialized before the archived 59 // object sub-graphs can be accessed at runtime. 60 GrowableArray<Klass*>* _subgraph_object_klasses; 61 // A list of _k's static fields as the entry points of archived sub-graphs. 62 // For each entry field, it is a tuple of field_offset, field_value and 63 // is_closed_archive flag. 64 GrowableArray<juint>* _subgraph_entry_fields; 65 66 public: 67 KlassSubGraphInfo(Klass* k) : 68 _k(k), _subgraph_object_klasses(NULL), 69 _subgraph_entry_fields(NULL) {} 70 ~KlassSubGraphInfo() { 71 if (_subgraph_object_klasses != NULL) { 72 delete _subgraph_object_klasses; 73 } 74 if (_subgraph_entry_fields != NULL) { 75 delete _subgraph_entry_fields; 76 } 77 }; 78 79 Klass* klass() { return _k; } 80 GrowableArray<Klass*>* subgraph_object_klasses() { 81 return _subgraph_object_klasses; 82 } 83 GrowableArray<juint>* subgraph_entry_fields() { 84 return _subgraph_entry_fields; 85 } 86 void add_subgraph_entry_field(int static_field_offset, oop v, 87 bool is_closed_archive); 88 void add_subgraph_object_klass(Klass *orig_k, Klass *relocated_k); 89 int num_subgraph_object_klasses() { 90 return _subgraph_object_klasses == NULL ? 0 : 91 _subgraph_object_klasses->length(); 92 } 93 }; 94 95 // An archived record of object sub-graphs reachable from static 96 // fields within _k's mirror. The record is reloaded from the archive 97 // at runtime. 98 class ArchivedKlassSubGraphInfoRecord { 99 private: 100 Klass* _k; 101 102 // contains pairs of field offset and value for each subgraph entry field 103 Array<juint>* _entry_field_records; 104 105 // klasses of objects in archived sub-graphs referenced from the entry points 106 // (static fields) in the containing class 107 Array<Klass*>* _subgraph_object_klasses; 108 public: 109 ArchivedKlassSubGraphInfoRecord() : 110 _k(NULL), _entry_field_records(NULL), _subgraph_object_klasses(NULL) {} 111 void init(KlassSubGraphInfo* info); 112 Klass* klass() const { return _k; } 113 Array<juint>* entry_field_records() const { return _entry_field_records; } 114 Array<Klass*>* subgraph_object_klasses() const { return _subgraph_object_klasses; } 115 }; 116 #endif // INCLUDE_CDS_JAVA_HEAP 117 118 class HeapShared: AllStatic { 119 friend class VerifySharedOopClosure; 120 private: 121 122 #if INCLUDE_CDS_JAVA_HEAP 123 static bool _closed_archive_heap_region_mapped; 124 static bool _open_archive_heap_region_mapped; 125 static bool _archive_heap_region_fixed; 126 127 static bool oop_equals(oop const& p1, oop const& p2) { 128 return p1 == p2; 129 } 130 static unsigned oop_hash(oop const& p); 131 132 typedef ResourceHashtable<oop, oop, 133 HeapShared::oop_hash, 134 HeapShared::oop_equals, 135 15889, // prime number 136 ResourceObj::C_HEAP> ArchivedObjectCache; 137 static ArchivedObjectCache* _archived_object_cache; 138 139 static bool klass_equals(Klass* const& p1, Klass* const& p2) { 140 return primitive_equals<Klass*>(p1, p2); 141 } 142 143 static unsigned klass_hash(Klass* const& klass) { 144 // Generate deterministic hashcode even if SharedBaseAddress is changed due to ASLR. 145 return primitive_hash<address>(address(klass) - SharedBaseAddress); 146 } 147 148 class DumpTimeKlassSubGraphInfoTable 149 : public ResourceHashtable<Klass*, KlassSubGraphInfo, 150 HeapShared::klass_hash, 151 HeapShared::klass_equals, 152 137, // prime number 153 ResourceObj::C_HEAP> { 154 public: 155 int _count; 156 }; 157 158 public: // solaris compiler wants this for RunTimeKlassSubGraphInfoTable 159 inline static bool record_equals_compact_hashtable_entry( 160 const ArchivedKlassSubGraphInfoRecord* value, const Klass* key, int len_unused) { 161 return (value->klass() == key); 162 } 163 164 private: 165 typedef OffsetCompactHashtable< 166 const Klass*, 167 const ArchivedKlassSubGraphInfoRecord*, 168 record_equals_compact_hashtable_entry 169 > RunTimeKlassSubGraphInfoTable; 170 171 static DumpTimeKlassSubGraphInfoTable* _dump_time_subgraph_info_table; 172 static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table; 173 174 static void check_closed_archive_heap_region_object(InstanceKlass* k, 175 Thread* THREAD); 176 177 static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[], 178 int num, 179 bool is_closed_archive, 180 Thread* THREAD); 181 182 // Archive object sub-graph starting from the given static field 183 // in Klass k's mirror. 184 static void archive_reachable_objects_from_static_field( 185 InstanceKlass* k, const char* klass_name, 186 int field_offset, const char* field_name, 187 bool is_closed_archive, TRAPS); 188 189 static void verify_subgraph_from_static_field( 190 InstanceKlass* k, int field_offset) PRODUCT_RETURN; 191 static void verify_reachable_objects_from(oop obj, bool is_archived) PRODUCT_RETURN; 192 static void verify_subgraph_from(oop orig_obj) PRODUCT_RETURN; 193 194 static KlassSubGraphInfo* get_subgraph_info(Klass *k); 195 196 static void init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[], 197 int num, Thread* THREAD); 198 199 // Used by decode_from_archive 200 static address _narrow_oop_base; 201 static int _narrow_oop_shift; 202 203 typedef ResourceHashtable<oop, bool, 204 HeapShared::oop_hash, 205 HeapShared::oop_equals, 206 15889, // prime number 207 ResourceObj::C_HEAP> SeenObjectsTable; 208 209 static SeenObjectsTable *_seen_objects_table; 210 211 static void init_seen_objects_table() { 212 assert(_seen_objects_table == NULL, "must be"); 213 _seen_objects_table = new (ResourceObj::C_HEAP, mtClass)SeenObjectsTable(); 214 } 215 static void delete_seen_objects_table() { 216 assert(_seen_objects_table != NULL, "must be"); 217 delete _seen_objects_table; 218 _seen_objects_table = NULL; 219 } 220 221 // Statistics (for one round of start_recording_subgraph ... done_recording_subgraph) 222 static int _num_new_walked_objs; 223 static int _num_new_archived_objs; 224 static int _num_old_recorded_klasses; 225 226 // Statistics (for all archived subgraphs) 227 static int _num_total_subgraph_recordings; 228 static int _num_total_walked_objs; 229 static int _num_total_archived_objs; 230 static int _num_total_recorded_klasses; 231 static int _num_total_verifications; 232 233 static void start_recording_subgraph(InstanceKlass *k, const char* klass_name); 234 static void done_recording_subgraph(InstanceKlass *k, const char* klass_name); 235 236 static bool has_been_seen_during_subgraph_recording(oop obj); 237 static void set_has_been_seen_during_subgraph_recording(oop obj); 238 239 public: 240 static void create_archived_object_cache() { 241 _archived_object_cache = 242 new (ResourceObj::C_HEAP, mtClass)ArchivedObjectCache(); 243 } 244 static void destroy_archived_object_cache() { 245 delete _archived_object_cache; 246 _archived_object_cache = NULL; 247 } 248 static ArchivedObjectCache* archived_object_cache() { 249 return _archived_object_cache; 250 } 251 252 static oop find_archived_heap_object(oop obj); 253 static oop archive_heap_object(oop obj, Thread* THREAD); 254 static oop materialize_archived_object(narrowOop v); 255 256 static void archive_klass_objects(Thread* THREAD); 257 258 static void set_archive_heap_region_fixed() { 259 _archive_heap_region_fixed = true; 260 } 261 static bool archive_heap_region_fixed() { 262 return _archive_heap_region_fixed; 263 } 264 265 static void archive_java_heap_objects(GrowableArray<MemRegion> *closed, 266 GrowableArray<MemRegion> *open); 267 static void copy_closed_archive_heap_objects(GrowableArray<MemRegion> * closed_archive); 268 static void copy_open_archive_heap_objects(GrowableArray<MemRegion> * open_archive); 269 270 static oop archive_reachable_objects_from(int level, 271 KlassSubGraphInfo* subgraph_info, 272 oop orig_obj, 273 bool is_closed_archive, 274 TRAPS); 275 276 static ResourceBitMap calculate_oopmap(MemRegion region); 277 #endif // INCLUDE_CDS_JAVA_HEAP 278 279 public: 280 static void run_full_gc_in_vm_thread() NOT_CDS_JAVA_HEAP_RETURN; 281 282 static bool is_heap_object_archiving_allowed() { 283 CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);) 284 NOT_CDS_JAVA_HEAP(return false;) 285 } 286 287 static bool is_heap_region(int idx) { 288 CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_closed_archive_heap_region && 289 idx <= MetaspaceShared::last_open_archive_heap_region)); 290 NOT_CDS_JAVA_HEAP_RETURN_(false); 291 } 292 293 static void set_closed_archive_heap_region_mapped() { 294 CDS_JAVA_HEAP_ONLY(_closed_archive_heap_region_mapped = true); 295 NOT_CDS_JAVA_HEAP_RETURN; 296 } 297 static bool closed_archive_heap_region_mapped() { 298 CDS_JAVA_HEAP_ONLY(return _closed_archive_heap_region_mapped); 299 NOT_CDS_JAVA_HEAP_RETURN_(false); 300 } 301 static void set_open_archive_heap_region_mapped() { 302 CDS_JAVA_HEAP_ONLY(_open_archive_heap_region_mapped = true); 303 NOT_CDS_JAVA_HEAP_RETURN; 304 } 305 static bool open_archive_heap_region_mapped() { 306 CDS_JAVA_HEAP_ONLY(return _open_archive_heap_region_mapped); 307 NOT_CDS_JAVA_HEAP_RETURN_(false); 308 } 309 310 static void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; 311 312 inline static bool is_archived_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false); 313 314 static void initialize_from_archived_subgraph(Klass* k) NOT_CDS_JAVA_HEAP_RETURN; 315 316 // NarrowOops stored in the CDS archive may use a different encoding scheme 317 // than CompressedOops::{base,shift} -- see FileMapInfo::map_heap_regions_impl. 318 // To decode them, do not use CompressedOops::decode_not_null. Use this 319 // function instead. 320 inline static oop decode_from_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL); 321 322 static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN; 323 324 static void patch_archived_heap_embedded_pointers(MemRegion mem, address oopmap, 325 size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN; 326 327 static void init_subgraph_entry_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN; 328 static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN; 329 static void serialize_subgraph_info_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; 330 }; 331 #endif // SHARE_MEMORY_HEAPSHARED_HPP