< prev index next >

src/hotspot/share/memory/heapShared.cpp

Print this page


  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.inline.hpp"
  27 #include "classfile/symbolTable.hpp"
  28 #include "classfile/vmSymbols.hpp"
  29 #include "logging/log.hpp"
  30 #include "logging/logMessage.hpp"
  31 #include "logging/logStream.hpp"
  32 #include "memory/heapShared.inline.hpp"
  33 #include "memory/iterator.inline.hpp"
  34 #include "memory/metadataFactory.hpp"
  35 #include "memory/metaspaceClosure.hpp"
  36 #include "memory/metaspaceShared.inline.hpp"
  37 #include "memory/resourceArea.hpp"
  38 #include "oops/compressedOops.inline.hpp"
  39 #include "oops/oop.inline.hpp"
  40 #include "runtime/fieldDescriptor.inline.hpp"
  41 #include "utilities/bitMap.inline.hpp"
  42 
  43 #if INCLUDE_CDS_JAVA_HEAP
  44 KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
  45 int HeapShared::_num_archived_subgraph_info_records = 0;
  46 Array<ArchivedKlassSubGraphInfoRecord>* HeapShared::_archived_subgraph_info_records = NULL;
  47 
  48 KlassSubGraphInfo* HeapShared::find_subgraph_info(Klass* k) {
  49   KlassSubGraphInfo* info = _subgraph_info_list;
  50   while (info != NULL) {
  51     if (info->klass() == k) {
  52       return info;
  53     }
  54     info = info->next();
  55   }
  56   return NULL;
  57 }
  58 
  59 // Get the subgraph_info for Klass k. A new subgraph_info is created if
  60 // there is no existing one for k. The subgraph_info records the relocated
  61 // Klass* of the original k.
  62 KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
  63   Klass* relocated_k = MetaspaceShared::get_relocated_klass(k);
  64   KlassSubGraphInfo* info = find_subgraph_info(relocated_k);
  65   if (info != NULL) {
  66     return info;


  67   }
  68 
  69   info = new KlassSubGraphInfo(relocated_k, _subgraph_info_list);
  70   _subgraph_info_list = info;
  71   return info;
  72 }
  73 
  74 address   HeapShared::_narrow_oop_base;
  75 int       HeapShared::_narrow_oop_shift;
  76 
  77 int HeapShared::num_of_subgraph_infos() {
  78   int num = 0;
  79   KlassSubGraphInfo* info = _subgraph_info_list;
  80   while (info != NULL) {
  81     num ++;
  82     info = info->next();
  83   }
  84   return num;
  85 }
  86 
  87 // Add an entry field to the current KlassSubGraphInfo.
  88 void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
  89   assert(DumpSharedSpaces, "dump time only");
  90   if (_subgraph_entry_fields == NULL) {
  91     _subgraph_entry_fields =
  92       new(ResourceObj::C_HEAP, mtClass) GrowableArray<juint>(10, true);
  93   }
  94   _subgraph_entry_fields->append((juint)static_field_offset);
  95   _subgraph_entry_fields->append(CompressedOops::encode(v));
  96 }
  97 
  98 // Add the Klass* for an object in the current KlassSubGraphInfo's subgraphs.
  99 // Only objects of boot classes can be included in sub-graph.
 100 void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k, Klass *relocated_k) {
 101   assert(DumpSharedSpaces, "dump time only");
 102   assert(relocated_k == MetaspaceShared::get_relocated_klass(orig_k),
 103          "must be the relocated Klass in the shared space");
 104 
 105   if (_subgraph_object_klasses == NULL) {
 106     _subgraph_object_klasses =


 139     }
 140   } else {
 141     assert(relocated_k->is_typeArray_klass(), "must be");
 142     // Primitive type arrays are created early during Universe::genesis.
 143     return;
 144   }
 145 
 146   if (log_is_enabled(Debug, cds, heap)) {
 147     if (!_subgraph_object_klasses->contains(relocated_k)) {
 148       ResourceMark rm;
 149       log_debug(cds, heap)("Adding klass %s", orig_k->external_name());
 150     }
 151   }
 152 
 153   _subgraph_object_klasses->append_if_missing(relocated_k);
 154 }
 155 
 156 // Initialize an archived subgraph_info_record from the given KlassSubGraphInfo.
 157 void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) {
 158   _k = info->klass();
 159   _next = NULL;
 160   _entry_field_records = NULL;
 161   _subgraph_object_klasses = NULL;
 162 
 163   // populate the entry fields
 164   GrowableArray<juint>* entry_fields = info->subgraph_entry_fields();
 165   if (entry_fields != NULL) {
 166     int num_entry_fields = entry_fields->length();
 167     assert(num_entry_fields % 2 == 0, "sanity");
 168     _entry_field_records =
 169       MetaspaceShared::new_ro_array<juint>(num_entry_fields);
 170     for (int i = 0 ; i < num_entry_fields; i++) {
 171       _entry_field_records->at_put(i, entry_fields->at(i));
 172     }
 173   }
 174 
 175   // the Klasses of the objects in the sub-graphs
 176   GrowableArray<Klass*>* subgraph_object_klasses = info->subgraph_object_klasses();
 177   if (subgraph_object_klasses != NULL) {
 178     int num_subgraphs_klasses = subgraph_object_klasses->length();
 179     _subgraph_object_klasses =
 180       MetaspaceShared::new_ro_array<Klass*>(num_subgraphs_klasses);
 181     for (int i = 0; i < num_subgraphs_klasses; i++) {
 182       Klass* subgraph_k = subgraph_object_klasses->at(i);
 183       if (log_is_enabled(Info, cds, heap)) {
 184         ResourceMark rm;
 185         log_info(cds, heap)(
 186           "Archived object klass %s (%2d) => %s",
 187           _k->external_name(), i, subgraph_k->external_name());
 188       }
 189       _subgraph_object_klasses->at_put(i, subgraph_k);
 190     }
 191   }
 192 }
 193 





















 194 // Build the records of archived subgraph infos, which include:
 195 // - Entry points to all subgraphs from the containing class mirror. The entry
 196 //   points are static fields in the mirror. For each entry point, the field
 197 //   offset and value are recorded in the sub-graph info. The value are stored
 198 //   back to the corresponding field at runtime.
 199 // - A list of klasses that need to be loaded/initialized before archived
 200 //   java object sub-graph can be accessed at runtime.
 201 //
 202 // The records are saved in the archive file and reloaded at runtime.
 203 //
 204 // Layout of the archived subgraph info records:
 205 //
 206 // records_size | num_records | records*
 207 // ArchivedKlassSubGraphInfoRecord | entry_fields | subgraph_object_klasses
 208 size_t HeapShared::build_archived_subgraph_info_records(int num_records) {
 209   // remember the start address
 210   char* start_p = MetaspaceShared::read_only_space_top();
 211 
 212   // now populate the archived subgraph infos, which will be saved in the
 213   // archive file
 214   _archived_subgraph_info_records =
 215     MetaspaceShared::new_ro_array<ArchivedKlassSubGraphInfoRecord>(num_records);
 216   KlassSubGraphInfo* info = _subgraph_info_list;
 217   int i = 0;
 218   while (info != NULL) {
 219     assert(i < _archived_subgraph_info_records->length(), "sanity");
 220     ArchivedKlassSubGraphInfoRecord* record =
 221       _archived_subgraph_info_records->adr_at(i);
 222     record->init(info);
 223     info = info->next();
 224     i ++;
 225   }
 226 
 227   // _subgraph_info_list is no longer needed
 228   delete _subgraph_info_list;
 229   _subgraph_info_list = NULL;
 230 
 231   char* end_p = MetaspaceShared::read_only_space_top();
 232   size_t records_size = end_p - start_p;
 233   return records_size;
 234 }
 235 
 236 // Write the subgraph info records in the shared _ro region
 237 void HeapShared::write_archived_subgraph_infos() {
 238   assert(DumpSharedSpaces, "dump time only");
 239 
 240   Array<intptr_t>* records_header = MetaspaceShared::new_ro_array<intptr_t>(3);



 241 
 242   _num_archived_subgraph_info_records = num_of_subgraph_infos();
 243   size_t records_size = build_archived_subgraph_info_records(
 244                              _num_archived_subgraph_info_records);
 245 
 246   // Now write the header information:
 247   // records_size, num_records, _archived_subgraph_info_records
 248   assert(records_header != NULL, "sanity");
 249   intptr_t* p = (intptr_t*)(records_header->data());
 250   *p = (intptr_t)records_size;
 251   p ++;
 252   *p = (intptr_t)_num_archived_subgraph_info_records;
 253   p ++;
 254   *p = (intptr_t)_archived_subgraph_info_records;
 255 }
 256 
 257 char* HeapShared::read_archived_subgraph_infos(char* buffer) {
 258   Array<intptr_t>* records_header = (Array<intptr_t>*)buffer;
 259   intptr_t* p = (intptr_t*)(records_header->data());
 260   size_t records_size = (size_t)(*p);
 261   p ++;
 262   _num_archived_subgraph_info_records = *p;
 263   p ++;
 264   _archived_subgraph_info_records =
 265     (Array<ArchivedKlassSubGraphInfoRecord>*)(*p);
 266 
 267   buffer = (char*)_archived_subgraph_info_records + records_size;
 268   return buffer;

 269 }
 270 
 271 void HeapShared::initialize_from_archived_subgraph(Klass* k) {
 272   if (!MetaspaceShared::open_archive_heap_region_mapped()) {
 273     return; // nothing to do
 274   }
 275 
 276   if (_num_archived_subgraph_info_records == 0) {
 277     return; // no subgraph info records
 278   }
 279 
 280   // Initialize from archived data. Currently this is done only
 281   // during VM initialization time. No lock is needed.

 282   Thread* THREAD = Thread::current();
 283   for (int i = 0; i < _archived_subgraph_info_records->length(); i++) {
 284     ArchivedKlassSubGraphInfoRecord* record = _archived_subgraph_info_records->adr_at(i);
 285     if (record->klass() == k) {



 286       int i;
 287       // Found the archived subgraph info record for the requesting klass.
 288       // Load/link/initialize the klasses of the objects in the subgraph.
 289       // NULL class loader is used.
 290       Array<Klass*>* klasses = record->subgraph_object_klasses();
 291       if (klasses != NULL) {
 292         for (i = 0; i < klasses->length(); i++) {
 293           Klass* obj_k = klasses->at(i);
 294           Klass* resolved_k = SystemDictionary::resolve_or_null(
 295                                                 (obj_k)->name(), THREAD);
 296           if (resolved_k != obj_k) {
 297             return;
 298           }
 299           if ((obj_k)->is_instance_klass()) {
 300             InstanceKlass* ik = InstanceKlass::cast(obj_k);
 301             ik->initialize(THREAD);
 302           } else if ((obj_k)->is_objArray_klass()) {
 303             ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k);
 304             oak->initialize(THREAD);
 305           }
 306         }
 307       }


 313         // subgraphs referenced from k in this case.
 314         return;
 315       }
 316 
 317       // Load the subgraph entry fields from the record and store them back to
 318       // the corresponding fields within the mirror.
 319       oop m = k->java_mirror();
 320       Array<juint>* entry_field_records = record->entry_field_records();
 321       if (entry_field_records != NULL) {
 322         int efr_len = entry_field_records->length();
 323         assert(efr_len % 2 == 0, "sanity");
 324         for (i = 0; i < efr_len;) {
 325           int field_offset = entry_field_records->at(i);
 326           // The object refereced by the field becomes 'known' by GC from this
 327           // point. All objects in the subgraph reachable from the object are
 328           // also 'known' by GC.
 329           oop v = MetaspaceShared::materialize_archived_object(
 330             entry_field_records->at(i+1));
 331           m->obj_field_put(field_offset, v);
 332           i += 2;
 333         }

 334       }
 335 
 336       // Done. Java code can see the archived sub-graphs referenced from k's
 337       // mirror after this point.
 338       return;
 339     }
 340   }
 341 }
 342 
 343 class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
 344   int _level;
 345   bool _record_klasses_only;
 346   KlassSubGraphInfo* _subgraph_info;
 347   oop _orig_referencing_obj;
 348   oop _archived_referencing_obj;
 349   Thread* _thread;
 350  public:
 351   WalkOopAndArchiveClosure(int level, bool record_klasses_only,
 352                            KlassSubGraphInfo* subgraph_info,
 353                            oop orig, oop archived, TRAPS) :
 354     _level(level), _record_klasses_only(record_klasses_only),
 355     _subgraph_info(subgraph_info),
 356     _orig_referencing_obj(orig), _archived_referencing_obj(archived),
 357     _thread(THREAD) {}
 358   void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }


 685   Symbol* _field_name;
 686   bool _found;
 687   int _offset;
 688 public:
 689   ArchivableStaticFieldFinder(InstanceKlass* ik, Symbol* field_name) :
 690     _ik(ik), _field_name(field_name), _found(false), _offset(-1) {}
 691 
 692   virtual void do_field(fieldDescriptor* fd) {
 693     if (fd->name() == _field_name) {
 694       assert(!_found, "fields cannot be overloaded");
 695       assert(fd->field_type() == T_OBJECT || fd->field_type() == T_ARRAY, "can archive only obj or array fields");
 696       _found = true;
 697       _offset = fd->offset();
 698     }
 699   }
 700   bool found()     { return _found;  }
 701   int offset()     { return _offset; }
 702 };
 703 
 704 void HeapShared::init_archivable_static_fields(Thread* THREAD) {


 705   for (int i = 0; i < num_archivable_static_fields; i++) {
 706     ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
 707     TempNewSymbol klass_name =  SymbolTable::new_symbol(info->klass_name, THREAD);
 708     TempNewSymbol field_name =  SymbolTable::new_symbol(info->field_name, THREAD);
 709 
 710     Klass* k = SystemDictionary::resolve_or_null(klass_name, THREAD);
 711     assert(k != NULL && !HAS_PENDING_EXCEPTION, "class must exist");
 712     InstanceKlass* ik = InstanceKlass::cast(k);
 713 
 714     ArchivableStaticFieldFinder finder(ik, field_name);
 715     ik->do_local_static_fields(&finder);
 716     assert(finder.found(), "field must exist");
 717 
 718     info->klass = ik;
 719     info->offset = finder.offset();
 720   }
 721 }
 722 
 723 void HeapShared::archive_static_fields(Thread* THREAD) {
 724   // For each class X that has one or more archived fields:




  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.inline.hpp"
  27 #include "classfile/symbolTable.hpp"
  28 #include "classfile/vmSymbols.hpp"
  29 #include "logging/log.hpp"
  30 #include "logging/logMessage.hpp"
  31 #include "logging/logStream.hpp"
  32 #include "memory/heapShared.inline.hpp"
  33 #include "memory/iterator.inline.hpp"
  34 #include "memory/metadataFactory.hpp"
  35 #include "memory/metaspaceClosure.hpp"
  36 #include "memory/metaspaceShared.inline.hpp"
  37 #include "memory/resourceArea.hpp"
  38 #include "oops/compressedOops.inline.hpp"
  39 #include "oops/oop.inline.hpp"
  40 #include "runtime/fieldDescriptor.inline.hpp"
  41 #include "utilities/bitMap.inline.hpp"
  42 
  43 #if INCLUDE_CDS_JAVA_HEAP
  44 address   HeapShared::_narrow_oop_base;
  45 int       HeapShared::_narrow_oop_shift;
  46 HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = NULL;
  47 HeapShared::RunTimeKlassSubGraphInfoTable   HeapShared::_run_time_subgraph_info_table;










  48 
  49 // Get the subgraph_info for Klass k. A new subgraph_info is created if
  50 // there is no existing one for k. The subgraph_info records the relocated
  51 // Klass* of the original k.
  52 KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
  53   Klass* relocated_k = MetaspaceShared::get_relocated_klass(k);
  54   KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k);
  55   if (info == NULL) {
  56     _dump_time_subgraph_info_table->put(relocated_k, KlassSubGraphInfo(relocated_k));
  57     info = _dump_time_subgraph_info_table->get(relocated_k);
  58     ++ _dump_time_subgraph_info_table->_count;
  59   }



  60   return info;
  61 }
  62 













  63 // Add an entry field to the current KlassSubGraphInfo.
  64 void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
  65   assert(DumpSharedSpaces, "dump time only");
  66   if (_subgraph_entry_fields == NULL) {
  67     _subgraph_entry_fields =
  68       new(ResourceObj::C_HEAP, mtClass) GrowableArray<juint>(10, true);
  69   }
  70   _subgraph_entry_fields->append((juint)static_field_offset);
  71   _subgraph_entry_fields->append(CompressedOops::encode(v));
  72 }
  73 
  74 // Add the Klass* for an object in the current KlassSubGraphInfo's subgraphs.
  75 // Only objects of boot classes can be included in sub-graph.
  76 void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k, Klass *relocated_k) {
  77   assert(DumpSharedSpaces, "dump time only");
  78   assert(relocated_k == MetaspaceShared::get_relocated_klass(orig_k),
  79          "must be the relocated Klass in the shared space");
  80 
  81   if (_subgraph_object_klasses == NULL) {
  82     _subgraph_object_klasses =


 115     }
 116   } else {
 117     assert(relocated_k->is_typeArray_klass(), "must be");
 118     // Primitive type arrays are created early during Universe::genesis.
 119     return;
 120   }
 121 
 122   if (log_is_enabled(Debug, cds, heap)) {
 123     if (!_subgraph_object_klasses->contains(relocated_k)) {
 124       ResourceMark rm;
 125       log_debug(cds, heap)("Adding klass %s", orig_k->external_name());
 126     }
 127   }
 128 
 129   _subgraph_object_klasses->append_if_missing(relocated_k);
 130 }
 131 
 132 // Initialize an archived subgraph_info_record from the given KlassSubGraphInfo.
 133 void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) {
 134   _k = info->klass();

 135   _entry_field_records = NULL;
 136   _subgraph_object_klasses = NULL;
 137 
 138   // populate the entry fields
 139   GrowableArray<juint>* entry_fields = info->subgraph_entry_fields();
 140   if (entry_fields != NULL) {
 141     int num_entry_fields = entry_fields->length();
 142     assert(num_entry_fields % 2 == 0, "sanity");
 143     _entry_field_records =
 144       MetaspaceShared::new_ro_array<juint>(num_entry_fields);
 145     for (int i = 0 ; i < num_entry_fields; i++) {
 146       _entry_field_records->at_put(i, entry_fields->at(i));
 147     }
 148   }
 149 
 150   // the Klasses of the objects in the sub-graphs
 151   GrowableArray<Klass*>* subgraph_object_klasses = info->subgraph_object_klasses();
 152   if (subgraph_object_klasses != NULL) {
 153     int num_subgraphs_klasses = subgraph_object_klasses->length();
 154     _subgraph_object_klasses =
 155       MetaspaceShared::new_ro_array<Klass*>(num_subgraphs_klasses);
 156     for (int i = 0; i < num_subgraphs_klasses; i++) {
 157       Klass* subgraph_k = subgraph_object_klasses->at(i);
 158       if (log_is_enabled(Info, cds, heap)) {
 159         ResourceMark rm;
 160         log_info(cds, heap)(
 161           "Archived object klass %s (%2d) => %s",
 162           _k->external_name(), i, subgraph_k->external_name());
 163       }
 164       _subgraph_object_klasses->at_put(i, subgraph_k);
 165     }
 166   }
 167 }
 168 
 169 struct CopyKlassSubGraphInfoToArchive : StackObj {
 170   CompactHashtableWriter* _writer;
 171   CopyKlassSubGraphInfoToArchive(CompactHashtableWriter* writer) : _writer(writer) {}
 172 
 173   bool do_entry(Klass* klass, KlassSubGraphInfo& info) {
 174 
 175     if (info.subgraph_object_klasses() != NULL || info.subgraph_entry_fields() != NULL) {
 176       ArchivedKlassSubGraphInfoRecord* record =
 177         (ArchivedKlassSubGraphInfoRecord*)MetaspaceShared::read_only_space_alloc(sizeof(ArchivedKlassSubGraphInfoRecord));
 178       record->init(&info);
 179 
 180       unsigned int hash = primitive_hash<Klass*>(klass);
 181       uintx deltax = MetaspaceShared::object_delta(record);
 182       guarantee(deltax <= MAX_SHARED_DELTA, "must not be");
 183       u4 delta = u4(deltax);
 184       _writer->add(hash, delta);
 185     }
 186     return true; // keep on iterating
 187   }
 188 };
 189 
 190 // Build the records of archived subgraph infos, which include:
 191 // - Entry points to all subgraphs from the containing class mirror. The entry
 192 //   points are static fields in the mirror. For each entry point, the field
 193 //   offset and value are recorded in the sub-graph info. The value are stored
 194 //   back to the corresponding field at runtime.
 195 // - A list of klasses that need to be loaded/initialized before archived
 196 //   java object sub-graph can be accessed at runtime.
 197 void HeapShared::create_hashtables() {
 198   // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive.
 199   DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table;
 200   CompactHashtableStats stats;

























 201 
 202   _run_time_subgraph_info_table.reset();







 203 
 204   int num_buckets = CompactHashtableWriter::default_num_buckets(d_table->_count);
 205   CompactHashtableWriter writer(num_buckets, &stats);
 206   CopyKlassSubGraphInfoToArchive copy(&writer);
 207   _dump_time_subgraph_info_table->iterate(&copy);
 208 
 209   writer.dump(&_run_time_subgraph_info_table, "subgraphs");
 210 }






















 211 
 212 // Read/write the headers of the hashtable(s) so they can be accessed quickly at runtime.
 213 void HeapShared::serialize_hashtables(SerializeClosure* soc) {
 214   _run_time_subgraph_info_table.serialize(soc);
 215 }
 216 
 217 void HeapShared::initialize_from_archived_subgraph(Klass* k) {
 218   if (!MetaspaceShared::open_archive_heap_region_mapped()) {
 219     return; // nothing to do
 220   }
 221 
 222   unsigned int hash = primitive_hash<Klass*>(k);
 223   ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0);

 224 
 225   // Initialize from archived data. Currently this is done only
 226   // during VM initialization time. No lock is needed.
 227   if (record != NULL) {
 228     Thread* THREAD = Thread::current();
 229     if (log_is_enabled(Info, cds, heap)) {
 230       ResourceMark rm;
 231       log_info(cds, heap)("initialize_from_archived_subgraph %p %s", k,
 232                           k->external_name());
 233     }
 234 
 235     int i;

 236     // Load/link/initialize the klasses of the objects in the subgraph.
 237     // NULL class loader is used.
 238     Array<Klass*>* klasses = record->subgraph_object_klasses();
 239     if (klasses != NULL) {
 240       for (i = 0; i < klasses->length(); i++) {
 241         Klass* obj_k = klasses->at(i);
 242         Klass* resolved_k = SystemDictionary::resolve_or_null(
 243                                               (obj_k)->name(), THREAD);
 244         if (resolved_k != obj_k) {
 245           return;
 246         }
 247         if ((obj_k)->is_instance_klass()) {
 248           InstanceKlass* ik = InstanceKlass::cast(obj_k);
 249           ik->initialize(THREAD);
 250         } else if ((obj_k)->is_objArray_klass()) {
 251           ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k);
 252           oak->initialize(THREAD);
 253         }
 254       }
 255     }


 261       // subgraphs referenced from k in this case.
 262       return;
 263     }
 264 
 265     // Load the subgraph entry fields from the record and store them back to
 266     // the corresponding fields within the mirror.
 267     oop m = k->java_mirror();
 268     Array<juint>* entry_field_records = record->entry_field_records();
 269     if (entry_field_records != NULL) {
 270       int efr_len = entry_field_records->length();
 271       assert(efr_len % 2 == 0, "sanity");
 272       for (i = 0; i < efr_len;) {
 273         int field_offset = entry_field_records->at(i);
 274         // The object refereced by the field becomes 'known' by GC from this
 275         // point. All objects in the subgraph reachable from the object are
 276         // also 'known' by GC.
 277         oop v = MetaspaceShared::materialize_archived_object(
 278             entry_field_records->at(i+1));
 279         m->obj_field_put(field_offset, v);
 280         i += 2;
 281 
 282         log_debug(cds, heap)("  %p init field @ %2d = %p", k, field_offset, (address)v);
 283       }
 284 
 285     // Done. Java code can see the archived sub-graphs referenced from k's
 286     // mirror after this point.

 287     }
 288   }
 289 }
 290 
 291 class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
 292   int _level;
 293   bool _record_klasses_only;
 294   KlassSubGraphInfo* _subgraph_info;
 295   oop _orig_referencing_obj;
 296   oop _archived_referencing_obj;
 297   Thread* _thread;
 298  public:
 299   WalkOopAndArchiveClosure(int level, bool record_klasses_only,
 300                            KlassSubGraphInfo* subgraph_info,
 301                            oop orig, oop archived, TRAPS) :
 302     _level(level), _record_klasses_only(record_klasses_only),
 303     _subgraph_info(subgraph_info),
 304     _orig_referencing_obj(orig), _archived_referencing_obj(archived),
 305     _thread(THREAD) {}
 306   void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }


 633   Symbol* _field_name;
 634   bool _found;
 635   int _offset;
 636 public:
 637   ArchivableStaticFieldFinder(InstanceKlass* ik, Symbol* field_name) :
 638     _ik(ik), _field_name(field_name), _found(false), _offset(-1) {}
 639 
 640   virtual void do_field(fieldDescriptor* fd) {
 641     if (fd->name() == _field_name) {
 642       assert(!_found, "fields cannot be overloaded");
 643       assert(fd->field_type() == T_OBJECT || fd->field_type() == T_ARRAY, "can archive only obj or array fields");
 644       _found = true;
 645       _offset = fd->offset();
 646     }
 647   }
 648   bool found()     { return _found;  }
 649   int offset()     { return _offset; }
 650 };
 651 
 652 void HeapShared::init_archivable_static_fields(Thread* THREAD) {
 653   _dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable();
 654 
 655   for (int i = 0; i < num_archivable_static_fields; i++) {
 656     ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
 657     TempNewSymbol klass_name =  SymbolTable::new_symbol(info->klass_name, THREAD);
 658     TempNewSymbol field_name =  SymbolTable::new_symbol(info->field_name, THREAD);
 659 
 660     Klass* k = SystemDictionary::resolve_or_null(klass_name, THREAD);
 661     assert(k != NULL && !HAS_PENDING_EXCEPTION, "class must exist");
 662     InstanceKlass* ik = InstanceKlass::cast(k);
 663 
 664     ArchivableStaticFieldFinder finder(ik, field_name);
 665     ik->do_local_static_fields(&finder);
 666     assert(finder.found(), "field must exist");
 667 
 668     info->klass = ik;
 669     info->offset = finder.offset();
 670   }
 671 }
 672 
 673 void HeapShared::archive_static_fields(Thread* THREAD) {
 674   // For each class X that has one or more archived fields:


< prev index next >