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