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   int full_module_graph_only;
  44   const char* field_name;  
  45   InstanceKlass* klass;
  46   int offset;
  47   BasicType type;
  48 };
  49 
  50 // A dump time sub-graph info for Klass _k. It includes the entry points
  51 // (static fields in _k's mirror) of the archived sub-graphs reachable
  52 // from _k's mirror. It also contains a list of Klasses of the objects
  53 // within the sub-graphs.
  54 class KlassSubGraphInfo: public CHeapObj<mtClass> {
  55  private:
  56   // The class that contains the static field(s) as the entry point(s)
  57   // of archived object sub-graph(s).
  58   Klass* _k;
  59   // A list of classes need to be loaded and initialized before the archived
  60   // object sub-graphs can be accessed at runtime.
  61   GrowableArray<Klass*>* _subgraph_object_klasses;
  62   // A list of _k's static fields as the entry points of archived sub-graphs.
  63   // For each entry field, it is a tuple of field_offset, field_value and
  64   // is_closed_archive flag.
  65   GrowableArray<juint>*  _subgraph_entry_fields;
  66 
  67  public:
  68   KlassSubGraphInfo(Klass* k) :
  69     _k(k),  _subgraph_object_klasses(NULL),
  70     _subgraph_entry_fields(NULL) {}
  71   ~KlassSubGraphInfo() {
  72     if (_subgraph_object_klasses != NULL) {
  73       delete _subgraph_object_klasses;
  74     }
  75     if (_subgraph_entry_fields != NULL) {
  76       delete _subgraph_entry_fields;
  77     }
  78   };
  79 
  80   Klass* klass()            { return _k; }
  81   GrowableArray<Klass*>* subgraph_object_klasses() {
  82     return _subgraph_object_klasses;
  83   }
  84   GrowableArray<juint>*  subgraph_entry_fields() {
  85     return _subgraph_entry_fields;
  86   }
  87   void add_subgraph_entry_field(int static_field_offset, oop v,
  88                                 bool is_closed_archive);
  89   void add_subgraph_object_klass(Klass *orig_k, Klass *relocated_k);
  90   int num_subgraph_object_klasses() {
  91     return _subgraph_object_klasses == NULL ? 0 :
  92            _subgraph_object_klasses->length();
  93   }
  94 };
  95 
  96 // An archived record of object sub-graphs reachable from static
  97 // fields within _k's mirror. The record is reloaded from the archive
  98 // at runtime.
  99 class ArchivedKlassSubGraphInfoRecord {
 100  private:
 101   Klass* _k;
 102 
 103   // contains pairs of field offset and value for each subgraph entry field
 104   Array<juint>* _entry_field_records;
 105 
 106   // klasses of objects in archived sub-graphs referenced from the entry points
 107   // (static fields) in the containing class
 108   Array<Klass*>* _subgraph_object_klasses;
 109  public:
 110   ArchivedKlassSubGraphInfoRecord() :
 111     _k(NULL), _entry_field_records(NULL), _subgraph_object_klasses(NULL) {}
 112   void init(KlassSubGraphInfo* info);
 113   Klass* klass() const { return _k; }
 114   Array<juint>*  entry_field_records() const { return _entry_field_records; }
 115   Array<Klass*>* subgraph_object_klasses() const { return _subgraph_object_klasses; }
 116 };
 117 #endif // INCLUDE_CDS_JAVA_HEAP
 118 
 119 class HeapShared: AllStatic {
 120   friend class VerifySharedOopClosure;
 121  private:
 122 
 123 #if INCLUDE_CDS_JAVA_HEAP
 124   static bool _closed_archive_heap_region_mapped;
 125   static bool _open_archive_heap_region_mapped;
 126   static bool _archive_heap_region_fixed;
 127 
 128   static bool oop_equals(oop const& p1, oop const& p2) {
 129     return p1 == p2;
 130   }
 131   static unsigned oop_hash(oop const& p);
 132 
 133   typedef ResourceHashtable<oop, oop,
 134       HeapShared::oop_hash,
 135       HeapShared::oop_equals,
 136       15889, // prime number
 137       ResourceObj::C_HEAP> ArchivedObjectCache;
 138   static ArchivedObjectCache* _archived_object_cache;
 139 
 140   static bool klass_equals(Klass* const& p1, Klass* const& p2) {
 141     return primitive_equals<Klass*>(p1, p2);
 142   }
 143 
 144   static unsigned klass_hash(Klass* const& klass) {
 145     // Generate deterministic hashcode even if SharedBaseAddress is changed due to ASLR.
 146     return primitive_hash<address>(address(klass) - SharedBaseAddress);
 147   }
 148 
 149   class DumpTimeKlassSubGraphInfoTable
 150     : public ResourceHashtable<Klass*, KlassSubGraphInfo,
 151                                HeapShared::klass_hash,
 152                                HeapShared::klass_equals,
 153                                137, // prime number
 154                                ResourceObj::C_HEAP> {
 155   public:
 156     int _count;
 157   };
 158 
 159 public: // solaris compiler wants this for RunTimeKlassSubGraphInfoTable
 160   inline static bool record_equals_compact_hashtable_entry(
 161        const ArchivedKlassSubGraphInfoRecord* value, const Klass* key, int len_unused) {
 162     return (value->klass() == key);
 163   }
 164 
 165 private:
 166   typedef OffsetCompactHashtable<
 167     const Klass*,
 168     const ArchivedKlassSubGraphInfoRecord*,
 169     record_equals_compact_hashtable_entry
 170     > RunTimeKlassSubGraphInfoTable;
 171 
 172   static DumpTimeKlassSubGraphInfoTable* _dump_time_subgraph_info_table;
 173   static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table;
 174 
 175   static void check_closed_archive_heap_region_object(InstanceKlass* k,
 176                                                       Thread* THREAD);
 177 
 178   static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[],
 179                                        int num,
 180                                        bool is_closed_archive,
 181                                        Thread* THREAD);
 182 
 183   // Archive object sub-graph starting from the given static field
 184   // in Klass k's mirror.
 185   static void archive_reachable_objects_from_static_field(
 186     InstanceKlass* k, const char* klass_name,
 187     int field_offset, const char* field_name,
 188     bool is_closed_archive, TRAPS);
 189 
 190   static void verify_subgraph_from_static_field(
 191     InstanceKlass* k, int field_offset) PRODUCT_RETURN;
 192   static void verify_reachable_objects_from(oop obj, bool is_archived) PRODUCT_RETURN;
 193   static void verify_subgraph_from(oop orig_obj) PRODUCT_RETURN;
 194 
 195   static KlassSubGraphInfo* get_subgraph_info(Klass *k);
 196 
 197   static void init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[],
 198                                          int num, Thread* THREAD);
 199 
 200   // Used by decode_from_archive
 201   static address _narrow_oop_base;
 202   static int     _narrow_oop_shift;
 203 
 204   typedef ResourceHashtable<oop, bool,
 205       HeapShared::oop_hash,
 206       HeapShared::oop_equals,
 207       15889, // prime number
 208       ResourceObj::C_HEAP> SeenObjectsTable;
 209 
 210   static SeenObjectsTable *_seen_objects_table;
 211 
 212   static void init_seen_objects_table() {
 213     assert(_seen_objects_table == NULL, "must be");
 214     _seen_objects_table = new (ResourceObj::C_HEAP, mtClass)SeenObjectsTable();
 215   }
 216   static void delete_seen_objects_table() {
 217     assert(_seen_objects_table != NULL, "must be");
 218     delete _seen_objects_table;
 219     _seen_objects_table = NULL;
 220   }
 221 
 222   // Statistics (for one round of start_recording_subgraph ... done_recording_subgraph)
 223   static int _num_new_walked_objs;
 224   static int _num_new_archived_objs;
 225   static int _num_old_recorded_klasses;
 226 
 227   // Statistics (for all archived subgraphs)
 228   static int _num_total_subgraph_recordings;
 229   static int _num_total_walked_objs;
 230   static int _num_total_archived_objs;
 231   static int _num_total_recorded_klasses;
 232   static int _num_total_verifications;
 233 
 234   static void start_recording_subgraph(InstanceKlass *k, const char* klass_name);
 235   static void done_recording_subgraph(InstanceKlass *k, const char* klass_name);
 236 
 237   static bool has_been_seen_during_subgraph_recording(oop obj);
 238   static void set_has_been_seen_during_subgraph_recording(oop obj);
 239 
 240   static void check_module_oop(oop orig_module_obj);
 241 
 242  public:
 243   static void reset_archived_object_states(TRAPS);
 244   static void create_archived_object_cache() {
 245     _archived_object_cache =
 246       new (ResourceObj::C_HEAP, mtClass)ArchivedObjectCache();
 247   }
 248   static void destroy_archived_object_cache() {
 249     delete _archived_object_cache;
 250     _archived_object_cache = NULL;
 251   }
 252   static ArchivedObjectCache* archived_object_cache() {
 253     return _archived_object_cache;
 254   }
 255 
 256   static oop find_archived_heap_object(oop obj);
 257   static oop archive_heap_object(oop obj, Thread* THREAD);
 258   static oop materialize_archived_object(narrowOop v);
 259 
 260   static void archive_klass_objects(Thread* THREAD);
 261 
 262   static void set_archive_heap_region_fixed() {
 263     _archive_heap_region_fixed = true;
 264   }
 265   static bool archive_heap_region_fixed() {
 266     return _archive_heap_region_fixed;
 267   }
 268 
 269   static void archive_java_heap_objects(GrowableArray<MemRegion> *closed,
 270                                         GrowableArray<MemRegion> *open);
 271   static void copy_closed_archive_heap_objects(GrowableArray<MemRegion> * closed_archive);
 272   static void copy_open_archive_heap_objects(GrowableArray<MemRegion> * open_archive);
 273 
 274   static oop archive_reachable_objects_from(int level,
 275                                             KlassSubGraphInfo* subgraph_info,
 276                                             oop orig_obj,
 277                                             bool is_closed_archive,
 278                                             TRAPS);
 279 
 280   static ResourceBitMap calculate_oopmap(MemRegion region);
 281 #endif // INCLUDE_CDS_JAVA_HEAP
 282 
 283  public:
 284   static void run_full_gc_in_vm_thread() NOT_CDS_JAVA_HEAP_RETURN;
 285 
 286   static bool is_heap_object_archiving_allowed() {
 287     CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);)
 288     NOT_CDS_JAVA_HEAP(return false;)
 289   }
 290 
 291   static bool is_heap_region(int idx) {
 292     CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_closed_archive_heap_region &&
 293                                idx <= MetaspaceShared::last_open_archive_heap_region));
 294     NOT_CDS_JAVA_HEAP_RETURN_(false);
 295   }
 296 
 297   static void set_closed_archive_heap_region_mapped() {
 298     CDS_JAVA_HEAP_ONLY(_closed_archive_heap_region_mapped = true);
 299     NOT_CDS_JAVA_HEAP_RETURN;
 300   }
 301   static bool closed_archive_heap_region_mapped() {
 302     CDS_JAVA_HEAP_ONLY(return _closed_archive_heap_region_mapped);
 303     NOT_CDS_JAVA_HEAP_RETURN_(false);
 304   }
 305   static void set_open_archive_heap_region_mapped() {
 306     CDS_JAVA_HEAP_ONLY(_open_archive_heap_region_mapped = true);
 307     NOT_CDS_JAVA_HEAP_RETURN;
 308   }
 309   static bool open_archive_heap_region_mapped() {
 310     CDS_JAVA_HEAP_ONLY(return _open_archive_heap_region_mapped);
 311     NOT_CDS_JAVA_HEAP_RETURN_(false);
 312   }
 313 
 314   static void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
 315 
 316   inline static bool is_archived_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false);
 317 
 318   static void initialize_from_archived_subgraph(Klass* k) NOT_CDS_JAVA_HEAP_RETURN;
 319 
 320   // NarrowOops stored in the CDS archive may use a different encoding scheme
 321   // than CompressedOops::{base,shift} -- see FileMapInfo::map_heap_regions_impl.
 322   // To decode them, do not use CompressedOops::decode_not_null. Use this
 323   // function instead.
 324   inline static oop decode_from_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
 325 
 326   static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN;
 327 
 328   static void patch_archived_heap_embedded_pointers(MemRegion mem, address  oopmap,
 329                                                     size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN;
 330 
 331   static void init_subgraph_entry_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
 332   static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN;
 333   static void serialize_subgraph_info_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
 334 };
 335 #endif // SHARE_MEMORY_HEAPSHARED_HPP