< prev index next >
src/hotspot/share/memory/heapShared.cpp
Print this page
*** 39,91 ****
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "utilities/bitMap.inline.hpp"
#if INCLUDE_CDS_JAVA_HEAP
! KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
! int HeapShared::_num_archived_subgraph_info_records = 0;
! Array<ArchivedKlassSubGraphInfoRecord>* HeapShared::_archived_subgraph_info_records = NULL;
!
! KlassSubGraphInfo* HeapShared::find_subgraph_info(Klass* k) {
! KlassSubGraphInfo* info = _subgraph_info_list;
! while (info != NULL) {
! if (info->klass() == k) {
! return info;
! }
! info = info->next();
! }
! return NULL;
! }
// Get the subgraph_info for Klass k. A new subgraph_info is created if
// there is no existing one for k. The subgraph_info records the relocated
// Klass* of the original k.
KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
Klass* relocated_k = MetaspaceShared::get_relocated_klass(k);
! KlassSubGraphInfo* info = find_subgraph_info(relocated_k);
! if (info != NULL) {
! return info;
}
-
- info = new KlassSubGraphInfo(relocated_k, _subgraph_info_list);
- _subgraph_info_list = info;
return info;
}
- address HeapShared::_narrow_oop_base;
- int HeapShared::_narrow_oop_shift;
-
- int HeapShared::num_of_subgraph_infos() {
- int num = 0;
- KlassSubGraphInfo* info = _subgraph_info_list;
- while (info != NULL) {
- num ++;
- info = info->next();
- }
- return num;
- }
-
// Add an entry field to the current KlassSubGraphInfo.
void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
assert(DumpSharedSpaces, "dump time only");
if (_subgraph_entry_fields == NULL) {
_subgraph_entry_fields =
--- 39,67 ----
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "utilities/bitMap.inline.hpp"
#if INCLUDE_CDS_JAVA_HEAP
! address HeapShared::_narrow_oop_base;
! int HeapShared::_narrow_oop_shift;
! HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = NULL;
! HeapShared::RunTimeKlassSubGraphInfoTable HeapShared::_run_time_subgraph_info_table;
// Get the subgraph_info for Klass k. A new subgraph_info is created if
// there is no existing one for k. The subgraph_info records the relocated
// Klass* of the original k.
KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
Klass* relocated_k = MetaspaceShared::get_relocated_klass(k);
! KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k);
! if (info == NULL) {
! _dump_time_subgraph_info_table->put(relocated_k, KlassSubGraphInfo(relocated_k));
! info = _dump_time_subgraph_info_table->get(relocated_k);
! ++ _dump_time_subgraph_info_table->_count;
}
return info;
}
// Add an entry field to the current KlassSubGraphInfo.
void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
assert(DumpSharedSpaces, "dump time only");
if (_subgraph_entry_fields == NULL) {
_subgraph_entry_fields =
*** 154,164 ****
}
// Initialize an archived subgraph_info_record from the given KlassSubGraphInfo.
void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) {
_k = info->klass();
- _next = NULL;
_entry_field_records = NULL;
_subgraph_object_klasses = NULL;
// populate the entry fields
GrowableArray<juint>* entry_fields = info->subgraph_entry_fields();
--- 130,139 ----
*** 189,292 ****
_subgraph_object_klasses->at_put(i, subgraph_k);
}
}
}
// Build the records of archived subgraph infos, which include:
// - Entry points to all subgraphs from the containing class mirror. The entry
// points are static fields in the mirror. For each entry point, the field
// offset and value are recorded in the sub-graph info. The value are stored
// back to the corresponding field at runtime.
// - A list of klasses that need to be loaded/initialized before archived
// java object sub-graph can be accessed at runtime.
! //
! // The records are saved in the archive file and reloaded at runtime.
! //
! // Layout of the archived subgraph info records:
! //
! // records_size | num_records | records*
! // ArchivedKlassSubGraphInfoRecord | entry_fields | subgraph_object_klasses
! size_t HeapShared::build_archived_subgraph_info_records(int num_records) {
! // remember the start address
! char* start_p = MetaspaceShared::read_only_space_top();
!
! // now populate the archived subgraph infos, which will be saved in the
! // archive file
! _archived_subgraph_info_records =
! MetaspaceShared::new_ro_array<ArchivedKlassSubGraphInfoRecord>(num_records);
! KlassSubGraphInfo* info = _subgraph_info_list;
! int i = 0;
! while (info != NULL) {
! assert(i < _archived_subgraph_info_records->length(), "sanity");
! ArchivedKlassSubGraphInfoRecord* record =
! _archived_subgraph_info_records->adr_at(i);
! record->init(info);
! info = info->next();
! i ++;
! }
!
! // _subgraph_info_list is no longer needed
! delete _subgraph_info_list;
! _subgraph_info_list = NULL;
! char* end_p = MetaspaceShared::read_only_space_top();
! size_t records_size = end_p - start_p;
! return records_size;
! }
!
! // Write the subgraph info records in the shared _ro region
! void HeapShared::write_archived_subgraph_infos() {
! assert(DumpSharedSpaces, "dump time only");
! Array<intptr_t>* records_header = MetaspaceShared::new_ro_array<intptr_t>(3);
! _num_archived_subgraph_info_records = num_of_subgraph_infos();
! size_t records_size = build_archived_subgraph_info_records(
! _num_archived_subgraph_info_records);
!
! // Now write the header information:
! // records_size, num_records, _archived_subgraph_info_records
! assert(records_header != NULL, "sanity");
! intptr_t* p = (intptr_t*)(records_header->data());
! *p = (intptr_t)records_size;
! p ++;
! *p = (intptr_t)_num_archived_subgraph_info_records;
! p ++;
! *p = (intptr_t)_archived_subgraph_info_records;
! }
!
! char* HeapShared::read_archived_subgraph_infos(char* buffer) {
! Array<intptr_t>* records_header = (Array<intptr_t>*)buffer;
! intptr_t* p = (intptr_t*)(records_header->data());
! size_t records_size = (size_t)(*p);
! p ++;
! _num_archived_subgraph_info_records = *p;
! p ++;
! _archived_subgraph_info_records =
! (Array<ArchivedKlassSubGraphInfoRecord>*)(*p);
! buffer = (char*)_archived_subgraph_info_records + records_size;
! return buffer;
}
void HeapShared::initialize_from_archived_subgraph(Klass* k) {
if (!MetaspaceShared::open_archive_heap_region_mapped()) {
return; // nothing to do
}
! if (_num_archived_subgraph_info_records == 0) {
! return; // no subgraph info records
! }
// Initialize from archived data. Currently this is done only
// during VM initialization time. No lock is needed.
Thread* THREAD = Thread::current();
! for (int i = 0; i < _archived_subgraph_info_records->length(); i++) {
! ArchivedKlassSubGraphInfoRecord* record = _archived_subgraph_info_records->adr_at(i);
! if (record->klass() == k) {
int i;
- // Found the archived subgraph info record for the requesting klass.
// Load/link/initialize the klasses of the objects in the subgraph.
// NULL class loader is used.
Array<Klass*>* klasses = record->subgraph_object_klasses();
if (klasses != NULL) {
for (i = 0; i < klasses->length(); i++) {
--- 164,240 ----
_subgraph_object_klasses->at_put(i, subgraph_k);
}
}
}
+ struct CopyKlassSubGraphInfoToArchive : StackObj {
+ CompactHashtableWriter* _writer;
+ CopyKlassSubGraphInfoToArchive(CompactHashtableWriter* writer) : _writer(writer) {}
+
+ bool do_entry(Klass* klass, KlassSubGraphInfo& info) {
+
+ if (info.subgraph_object_klasses() != NULL || info.subgraph_entry_fields() != NULL) {
+ ArchivedKlassSubGraphInfoRecord* record =
+ (ArchivedKlassSubGraphInfoRecord*)MetaspaceShared::read_only_space_alloc(sizeof(ArchivedKlassSubGraphInfoRecord));
+ record->init(&info);
+
+ unsigned int hash = primitive_hash<Klass*>(klass);
+ uintx deltax = MetaspaceShared::object_delta(record);
+ guarantee(deltax <= MAX_SHARED_DELTA, "must not be");
+ u4 delta = u4(deltax);
+ _writer->add(hash, delta);
+ }
+ return true; // keep on iterating
+ }
+ };
+
// Build the records of archived subgraph infos, which include:
// - Entry points to all subgraphs from the containing class mirror. The entry
// points are static fields in the mirror. For each entry point, the field
// offset and value are recorded in the sub-graph info. The value are stored
// back to the corresponding field at runtime.
// - A list of klasses that need to be loaded/initialized before archived
// java object sub-graph can be accessed at runtime.
! void HeapShared::create_hashtables() {
! // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive.
! DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table;
! CompactHashtableStats stats;
! _run_time_subgraph_info_table.reset();
! int num_buckets = CompactHashtableWriter::default_num_buckets(d_table->_count);
! CompactHashtableWriter writer(num_buckets, &stats);
! CopyKlassSubGraphInfoToArchive copy(&writer);
! _dump_time_subgraph_info_table->iterate(©);
! writer.dump(&_run_time_subgraph_info_table, "subgraphs");
! }
! // Read/write the headers of the hashtable(s) so they can be accessed quickly at runtime.
! void HeapShared::serialize_hashtables(SerializeClosure* soc) {
! _run_time_subgraph_info_table.serialize(soc);
}
void HeapShared::initialize_from_archived_subgraph(Klass* k) {
if (!MetaspaceShared::open_archive_heap_region_mapped()) {
return; // nothing to do
}
! unsigned int hash = primitive_hash<Klass*>(k);
! ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0);
// Initialize from archived data. Currently this is done only
// during VM initialization time. No lock is needed.
+ if (record != NULL) {
Thread* THREAD = Thread::current();
! if (log_is_enabled(Info, cds, heap)) {
! ResourceMark rm;
! log_info(cds, heap)("initialize_from_archived_subgraph %p %s", k,
! k->external_name());
! }
!
int i;
// Load/link/initialize the klasses of the objects in the subgraph.
// NULL class loader is used.
Array<Klass*>* klasses = record->subgraph_object_klasses();
if (klasses != NULL) {
for (i = 0; i < klasses->length(); i++) {
*** 328,343 ****
// also 'known' by GC.
oop v = MetaspaceShared::materialize_archived_object(
entry_field_records->at(i+1));
m->obj_field_put(field_offset, v);
i += 2;
! }
}
// Done. Java code can see the archived sub-graphs referenced from k's
// mirror after this point.
- return;
}
}
}
class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
--- 276,291 ----
// also 'known' by GC.
oop v = MetaspaceShared::materialize_archived_object(
entry_field_records->at(i+1));
m->obj_field_put(field_offset, v);
i += 2;
!
! log_debug(cds, heap)(" %p init field @ %2d = %p", k, field_offset, (address)v);
}
// Done. Java code can see the archived sub-graphs referenced from k's
// mirror after this point.
}
}
}
class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
*** 700,709 ****
--- 648,659 ----
bool found() { return _found; }
int offset() { return _offset; }
};
void HeapShared::init_archivable_static_fields(Thread* THREAD) {
+ _dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable();
+
for (int i = 0; i < num_archivable_static_fields; i++) {
ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
TempNewSymbol klass_name = SymbolTable::new_symbol(info->klass_name, THREAD);
TempNewSymbol field_name = SymbolTable::new_symbol(info->field_name, THREAD);
< prev index next >