src/hotspot/share/memory/heapShared.cpp
changeset 52047 7bc8b456e5ac
parent 51796 9d3a00c8c047
child 52062 8dbf1a13af49
equal deleted inserted replaced
52046:2a85adf3c330 52047:7bc8b456e5ac
    39 #include "oops/oop.inline.hpp"
    39 #include "oops/oop.inline.hpp"
    40 #include "runtime/fieldDescriptor.inline.hpp"
    40 #include "runtime/fieldDescriptor.inline.hpp"
    41 #include "utilities/bitMap.inline.hpp"
    41 #include "utilities/bitMap.inline.hpp"
    42 
    42 
    43 #if INCLUDE_CDS_JAVA_HEAP
    43 #if INCLUDE_CDS_JAVA_HEAP
    44 KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
    44 address   HeapShared::_narrow_oop_base;
    45 int HeapShared::_num_archived_subgraph_info_records = 0;
    45 int       HeapShared::_narrow_oop_shift;
    46 Array<ArchivedKlassSubGraphInfoRecord>* HeapShared::_archived_subgraph_info_records = NULL;
    46 HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = NULL;
    47 
    47 HeapShared::RunTimeKlassSubGraphInfoTable   HeapShared::_run_time_subgraph_info_table;
    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 
    48 
    59 // Get the subgraph_info for Klass k. A new subgraph_info is created if
    49 // 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
    50 // there is no existing one for k. The subgraph_info records the relocated
    61 // Klass* of the original k.
    51 // Klass* of the original k.
    62 KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
    52 KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
       
    53   assert(DumpSharedSpaces, "dump time only");
    63   Klass* relocated_k = MetaspaceShared::get_relocated_klass(k);
    54   Klass* relocated_k = MetaspaceShared::get_relocated_klass(k);
    64   KlassSubGraphInfo* info = find_subgraph_info(relocated_k);
    55   KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k);
    65   if (info != NULL) {
    56   if (info == NULL) {
    66     return info;
    57     _dump_time_subgraph_info_table->put(relocated_k, KlassSubGraphInfo(relocated_k));
    67   }
    58     info = _dump_time_subgraph_info_table->get(relocated_k);
    68 
    59     ++ _dump_time_subgraph_info_table->_count;
    69   info = new KlassSubGraphInfo(relocated_k, _subgraph_info_list);
    60   }
    70   _subgraph_info_list = info;
       
    71   return info;
    61   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 }
    62 }
    86 
    63 
    87 // Add an entry field to the current KlassSubGraphInfo.
    64 // Add an entry field to the current KlassSubGraphInfo.
    88 void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
    65 void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
    89   assert(DumpSharedSpaces, "dump time only");
    66   assert(DumpSharedSpaces, "dump time only");
   154 }
   131 }
   155 
   132 
   156 // Initialize an archived subgraph_info_record from the given KlassSubGraphInfo.
   133 // Initialize an archived subgraph_info_record from the given KlassSubGraphInfo.
   157 void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) {
   134 void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) {
   158   _k = info->klass();
   135   _k = info->klass();
   159   _next = NULL;
       
   160   _entry_field_records = NULL;
   136   _entry_field_records = NULL;
   161   _subgraph_object_klasses = NULL;
   137   _subgraph_object_klasses = NULL;
   162 
   138 
   163   // populate the entry fields
   139   // populate the entry fields
   164   GrowableArray<juint>* entry_fields = info->subgraph_entry_fields();
   140   GrowableArray<juint>* entry_fields = info->subgraph_entry_fields();
   189       _subgraph_object_klasses->at_put(i, subgraph_k);
   165       _subgraph_object_klasses->at_put(i, subgraph_k);
   190     }
   166     }
   191   }
   167   }
   192 }
   168 }
   193 
   169 
       
   170 struct CopyKlassSubGraphInfoToArchive : StackObj {
       
   171   CompactHashtableWriter* _writer;
       
   172   CopyKlassSubGraphInfoToArchive(CompactHashtableWriter* writer) : _writer(writer) {}
       
   173 
       
   174   bool do_entry(Klass* klass, KlassSubGraphInfo& info) {
       
   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 
   194 // Build the records of archived subgraph infos, which include:
   190 // Build the records of archived subgraph infos, which include:
   195 // - Entry points to all subgraphs from the containing class mirror. The entry
   191 // - 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
   192 //   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
   193 //   offset and value are recorded in the sub-graph info. The value are stored
   198 //   back to the corresponding field at runtime.
   194 //   back to the corresponding field at runtime.
   199 // - A list of klasses that need to be loaded/initialized before archived
   195 // - A list of klasses that need to be loaded/initialized before archived
   200 //   java object sub-graph can be accessed at runtime.
   196 //   java object sub-graph can be accessed at runtime.
   201 //
   197 void HeapShared::write_subgraph_info_table() {
   202 // The records are saved in the archive file and reloaded at runtime.
   198   // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive.
   203 //
   199   DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table;
   204 // Layout of the archived subgraph info records:
   200   CompactHashtableStats stats;
   205 //
   201 
   206 // records_size | num_records | records*
   202   _run_time_subgraph_info_table.reset();
   207 // ArchivedKlassSubGraphInfoRecord | entry_fields | subgraph_object_klasses
   203 
   208 size_t HeapShared::build_archived_subgraph_info_records(int num_records) {
   204   int num_buckets = CompactHashtableWriter::default_num_buckets(d_table->_count);
   209   // remember the start address
   205   CompactHashtableWriter writer(num_buckets, &stats);
   210   char* start_p = MetaspaceShared::read_only_space_top();
   206   CopyKlassSubGraphInfoToArchive copy(&writer);
   211 
   207   _dump_time_subgraph_info_table->iterate(&copy);
   212   // now populate the archived subgraph infos, which will be saved in the
   208 
   213   // archive file
   209   writer.dump(&_run_time_subgraph_info_table, "subgraphs");
   214   _archived_subgraph_info_records =
   210 }
   215     MetaspaceShared::new_ro_array<ArchivedKlassSubGraphInfoRecord>(num_records);
   211 
   216   KlassSubGraphInfo* info = _subgraph_info_list;
   212 void HeapShared::serialize_subgraph_info_table_header(SerializeClosure* soc) {
   217   int i = 0;
   213   _run_time_subgraph_info_table.serialize_header(soc);
   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 }
   214 }
   270 
   215 
   271 void HeapShared::initialize_from_archived_subgraph(Klass* k) {
   216 void HeapShared::initialize_from_archived_subgraph(Klass* k) {
   272   if (!MetaspaceShared::open_archive_heap_region_mapped()) {
   217   if (!MetaspaceShared::open_archive_heap_region_mapped()) {
   273     return; // nothing to do
   218     return; // nothing to do
   274   }
   219   }
   275 
   220   assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces");
   276   if (_num_archived_subgraph_info_records == 0) {
   221 
   277     return; // no subgraph info records
   222   unsigned int hash = primitive_hash<Klass*>(k);
   278   }
   223   ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0);
   279 
   224 
   280   // Initialize from archived data. Currently this is done only
   225   // Initialize from archived data. Currently this is done only
   281   // during VM initialization time. No lock is needed.
   226   // during VM initialization time. No lock is needed.
   282   Thread* THREAD = Thread::current();
   227   if (record != NULL) {
   283   for (int i = 0; i < _archived_subgraph_info_records->length(); i++) {
   228     Thread* THREAD = Thread::current();
   284     ArchivedKlassSubGraphInfoRecord* record = _archived_subgraph_info_records->adr_at(i);
   229     if (log_is_enabled(Info, cds, heap)) {
   285     if (record->klass() == k) {
   230       ResourceMark rm;
   286       int i;
   231       log_info(cds, heap)("initialize_from_archived_subgraph " PTR_FORMAT " %s", p2i(k),
   287       // Found the archived subgraph info record for the requesting klass.
   232                           k->external_name());
   288       // Load/link/initialize the klasses of the objects in the subgraph.
   233     }
   289       // NULL class loader is used.
   234 
   290       Array<Klass*>* klasses = record->subgraph_object_klasses();
   235     int i;
   291       if (klasses != NULL) {
   236     // Load/link/initialize the klasses of the objects in the subgraph.
   292         for (i = 0; i < klasses->length(); i++) {
   237     // NULL class loader is used.
   293           Klass* obj_k = klasses->at(i);
   238     Array<Klass*>* klasses = record->subgraph_object_klasses();
   294           Klass* resolved_k = SystemDictionary::resolve_or_null(
   239     if (klasses != NULL) {
   295                                                 (obj_k)->name(), THREAD);
   240       for (i = 0; i < klasses->length(); i++) {
   296           if (resolved_k != obj_k) {
   241         Klass* obj_k = klasses->at(i);
   297             return;
   242         Klass* resolved_k = SystemDictionary::resolve_or_null(
   298           }
   243                                               (obj_k)->name(), THREAD);
   299           if ((obj_k)->is_instance_klass()) {
   244         if (resolved_k != obj_k) {
   300             InstanceKlass* ik = InstanceKlass::cast(obj_k);
   245           return;
   301             ik->initialize(THREAD);
   246         }
   302           } else if ((obj_k)->is_objArray_klass()) {
   247         if ((obj_k)->is_instance_klass()) {
   303             ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k);
   248           InstanceKlass* ik = InstanceKlass::cast(obj_k);
   304             oak->initialize(THREAD);
   249           ik->initialize(THREAD);
   305           }
   250         } else if ((obj_k)->is_objArray_klass()) {
       
   251           ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k);
       
   252           oak->initialize(THREAD);
   306         }
   253         }
   307       }
   254       }
   308 
   255     }
   309       if (HAS_PENDING_EXCEPTION) {
   256 
   310         CLEAR_PENDING_EXCEPTION;
   257     if (HAS_PENDING_EXCEPTION) {
   311         // None of the field value will be set if there was an exception.
   258       CLEAR_PENDING_EXCEPTION;
   312         // The java code will not see any of the archived objects in the
   259       // None of the field value will be set if there was an exception.
   313         // subgraphs referenced from k in this case.
   260       // The java code will not see any of the archived objects in the
   314         return;
   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)("  " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v));
   315       }
   283       }
   316 
   284 
   317       // Load the subgraph entry fields from the record and store them back to
   285     // Done. Java code can see the archived sub-graphs referenced from k's
   318       // the corresponding fields within the mirror.
   286     // mirror after this point.
   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     }
   287     }
   340   }
   288   }
   341 }
   289 }
   342 
   290 
   343 class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
   291 class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
   700   bool found()     { return _found;  }
   648   bool found()     { return _found;  }
   701   int offset()     { return _offset; }
   649   int offset()     { return _offset; }
   702 };
   650 };
   703 
   651 
   704 void HeapShared::init_archivable_static_fields(Thread* THREAD) {
   652 void HeapShared::init_archivable_static_fields(Thread* THREAD) {
       
   653   _dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable();
       
   654 
   705   for (int i = 0; i < num_archivable_static_fields; i++) {
   655   for (int i = 0; i < num_archivable_static_fields; i++) {
   706     ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
   656     ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
   707     TempNewSymbol klass_name =  SymbolTable::new_symbol(info->klass_name, THREAD);
   657     TempNewSymbol klass_name =  SymbolTable::new_symbol(info->klass_name, THREAD);
   708     TempNewSymbol field_name =  SymbolTable::new_symbol(info->field_name, THREAD);
   658     TempNewSymbol field_name =  SymbolTable::new_symbol(info->field_name, THREAD);
   709 
   659