8282828: CDS uncompressed oops archive is not deterministic
Reviewed-by: erikj, ihse, ccheung
This commit is contained in:
Родитель
45ca81ff5f
Коммит
64b5b2b0b3
|
@ -324,7 +324,7 @@ compare_general_files() {
|
|||
! -name "*.cpl" ! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
|
||||
! -name "*.lib" ! -name "*.jmod" ! -name "*.exe" \
|
||||
! -name "*.obj" ! -name "*.o" ! -name "jspawnhelper" ! -name "*.a" \
|
||||
! -name "*.tar.gz" ! -name "classes_nocoops.jsa" ! -name "gtestLauncher" \
|
||||
! -name "*.tar.gz" ! -name "gtestLauncher" \
|
||||
! -name "*.map" \
|
||||
| $GREP -v "./bin/" | $SORT | $FILTER)
|
||||
|
||||
|
|
|
@ -1016,24 +1016,27 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||
#undef _LOG_PREFIX
|
||||
|
||||
// Log information about a region, whose address at dump time is [base .. top). At
|
||||
// runtime, this region will be mapped to runtime_base. runtime_base is 0 if this
|
||||
// runtime, this region will be mapped to requested_base. requested_base is 0 if this
|
||||
// region will be mapped at os-selected addresses (such as the bitmap region), or will
|
||||
// be accessed with os::read (the header).
|
||||
static void log_region(const char* name, address base, address top, address runtime_base) {
|
||||
//
|
||||
// Note: across -Xshare:dump runs, base may be different, but requested_base should
|
||||
// be the same as the archive contents should be deterministic.
|
||||
static void log_region(const char* name, address base, address top, address requested_base) {
|
||||
size_t size = top - base;
|
||||
base = runtime_base;
|
||||
top = runtime_base + size;
|
||||
base = requested_base;
|
||||
top = requested_base + size;
|
||||
log_info(cds, map)("[%-18s " PTR_FORMAT " - " PTR_FORMAT " " SIZE_FORMAT_W(9) " bytes]",
|
||||
name, p2i(base), p2i(top), size);
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
// open and closed archive regions
|
||||
static void log_heap_regions(const char* which, GrowableArray<MemRegion> *regions) {
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
for (int i = 0; i < regions->length(); i++) {
|
||||
address start = address(regions->at(i).start());
|
||||
address end = address(regions->at(i).end());
|
||||
log_region(which, start, end, start);
|
||||
log_region(which, start, end, to_requested(start));
|
||||
|
||||
while (start < end) {
|
||||
size_t byte_size;
|
||||
|
@ -1042,34 +1045,37 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||
if (original_oop != NULL) {
|
||||
ResourceMark rm;
|
||||
log_info(cds, map)(PTR_FORMAT ": @@ Object %s",
|
||||
p2i(start), original_oop->klass()->external_name());
|
||||
p2i(to_requested(start)), original_oop->klass()->external_name());
|
||||
byte_size = original_oop->size() * BytesPerWord;
|
||||
} else if (archived_oop == HeapShared::roots()) {
|
||||
// HeapShared::roots() is copied specially so it doesn't exist in
|
||||
// HeapShared::OriginalObjectTable. See HeapShared::copy_roots().
|
||||
log_info(cds, map)(PTR_FORMAT ": @@ Object HeapShared:roots (ObjArray)",
|
||||
p2i(start));
|
||||
log_info(cds, map)(PTR_FORMAT ": @@ Object HeapShared::roots (ObjArray)",
|
||||
p2i(to_requested(start)));
|
||||
byte_size = objArrayOopDesc::object_size(HeapShared::roots()->length()) * BytesPerWord;
|
||||
} else {
|
||||
// We have reached the end of the region
|
||||
break;
|
||||
}
|
||||
address oop_end = start + byte_size;
|
||||
log_data(start, oop_end, start, /*is_heap=*/true);
|
||||
log_data(start, oop_end, to_requested(start), /*is_heap=*/true);
|
||||
start = oop_end;
|
||||
}
|
||||
if (start < end) {
|
||||
log_info(cds, map)(PTR_FORMAT ": @@ Unused heap space " SIZE_FORMAT " bytes",
|
||||
p2i(start), size_t(end - start));
|
||||
log_data(start, end, start, /*is_heap=*/true);
|
||||
p2i(to_requested(start)), size_t(end - start));
|
||||
log_data(start, end, to_requested(start), /*is_heap=*/true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
static address to_requested(address p) {
|
||||
return HeapShared::to_requested_address(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Log all the data [base...top). Pretend that the base address
|
||||
// will be mapped to runtime_base at run-time.
|
||||
static void log_data(address base, address top, address runtime_base, bool is_heap = false) {
|
||||
// will be mapped to requested_base at run-time.
|
||||
static void log_data(address base, address top, address requested_base, bool is_heap = false) {
|
||||
assert(top >= base, "must be");
|
||||
|
||||
LogStreamHandle(Trace, cds, map) lsh;
|
||||
|
@ -1080,7 +1086,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||
// longs and doubles will be split into two words.
|
||||
unitsize = sizeof(narrowOop);
|
||||
}
|
||||
os::print_hex_dump(&lsh, base, top, unitsize, 32, runtime_base);
|
||||
os::print_hex_dump(&lsh, base, top, unitsize, 32, requested_base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1114,12 +1120,14 @@ public:
|
|||
log_region("bitmap", address(bitmap), bitmap_end, 0);
|
||||
log_data((address)bitmap, bitmap_end, 0);
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
if (closed_heap_regions != NULL) {
|
||||
log_heap_regions("closed heap region", closed_heap_regions);
|
||||
}
|
||||
if (open_heap_regions != NULL) {
|
||||
log_heap_regions("open heap region", open_heap_regions);
|
||||
}
|
||||
#endif
|
||||
|
||||
log_info(cds, map)("[End of CDS archive map]");
|
||||
}
|
||||
|
|
|
@ -265,8 +265,13 @@ void WriteClosure::do_oop(oop* o) {
|
|||
_dump_region->append_intptr_t(0);
|
||||
} else {
|
||||
assert(HeapShared::can_write(), "sanity");
|
||||
_dump_region->append_intptr_t(
|
||||
UseCompressedOops ? (intptr_t)CompressedOops::encode_not_null(*o) : (intptr_t)((void*)(*o)));
|
||||
intptr_t p;
|
||||
if (UseCompressedOops) {
|
||||
p = (intptr_t)CompressedOops::encode_not_null(*o);
|
||||
} else {
|
||||
p = cast_from_oop<intptr_t>(HeapShared::to_requested_address(*o));
|
||||
}
|
||||
_dump_region->append_intptr_t(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -251,8 +251,10 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment,
|
|||
_heap_begin = CompressedOops::begin();
|
||||
_heap_end = CompressedOops::end();
|
||||
} else {
|
||||
_heap_begin = (address)G1CollectedHeap::heap()->reserved().start();
|
||||
_heap_end = (address)G1CollectedHeap::heap()->reserved().end();
|
||||
address start = (address)G1CollectedHeap::heap()->reserved().start();
|
||||
address end = (address)G1CollectedHeap::heap()->reserved().end();
|
||||
_heap_begin = HeapShared::to_requested_address(start);
|
||||
_heap_end = HeapShared::to_requested_address(end);
|
||||
}
|
||||
}
|
||||
_compressed_oops = UseCompressedOops;
|
||||
|
|
|
@ -179,8 +179,9 @@ void HeapShared::fixup_regions() {
|
|||
}
|
||||
|
||||
unsigned HeapShared::oop_hash(oop const& p) {
|
||||
unsigned hash = (unsigned)p->identity_hash();
|
||||
return hash;
|
||||
// Do not call p->identity_hash() as that will update the
|
||||
// object header.
|
||||
return primitive_hash(cast_from_oop<intptr_t>(p));
|
||||
}
|
||||
|
||||
static void reset_states(oop obj, TRAPS) {
|
||||
|
@ -1577,9 +1578,12 @@ class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
|
|||
: _start(start), _oopmap(oopmap), _num_total_oops(0), _num_null_oops(0) {}
|
||||
|
||||
virtual void do_oop(narrowOop* p) {
|
||||
assert(UseCompressedOops, "sanity");
|
||||
_num_total_oops ++;
|
||||
narrowOop v = *p;
|
||||
if (!CompressedOops::is_null(v)) {
|
||||
// Note: HeapShared::to_requested_address() is not necessary because
|
||||
// the heap always starts at a deterministic address with UseCompressedOops==true.
|
||||
size_t idx = p - (narrowOop*)_start;
|
||||
_oopmap->set_bit(idx);
|
||||
} else {
|
||||
|
@ -1587,10 +1591,15 @@ class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
|
|||
}
|
||||
}
|
||||
virtual void do_oop(oop* p) {
|
||||
assert(!UseCompressedOops, "sanity");
|
||||
_num_total_oops ++;
|
||||
if ((*p) != NULL) {
|
||||
size_t idx = p - (oop*)_start;
|
||||
_oopmap->set_bit(idx);
|
||||
if (DumpSharedSpaces) {
|
||||
// Make heap content deterministic.
|
||||
*p = HeapShared::to_requested_address(*p);
|
||||
}
|
||||
} else {
|
||||
_num_null_oops ++;
|
||||
}
|
||||
|
@ -1599,6 +1608,34 @@ class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
|
|||
int num_null_oops() const { return _num_null_oops; }
|
||||
};
|
||||
|
||||
|
||||
address HeapShared::to_requested_address(address dumptime_addr) {
|
||||
assert(DumpSharedSpaces, "static dump time only");
|
||||
if (dumptime_addr == NULL || UseCompressedOops) {
|
||||
return dumptime_addr;
|
||||
}
|
||||
|
||||
// With UseCompressedOops==false, actual_base is selected by the OS so
|
||||
// it's different across -Xshare:dump runs.
|
||||
address actual_base = (address)G1CollectedHeap::heap()->reserved().start();
|
||||
address actual_end = (address)G1CollectedHeap::heap()->reserved().end();
|
||||
assert(actual_base <= dumptime_addr && dumptime_addr <= actual_end, "must be an address in the heap");
|
||||
|
||||
// We always write the objects as if the heap started at this address. This
|
||||
// makes the heap content deterministic.
|
||||
//
|
||||
// Note that at runtime, the heap address is also selected by the OS, so
|
||||
// the archive heap will not be mapped at 0x10000000. Instead, we will call
|
||||
// HeapShared::patch_embedded_pointers() to relocate the heap contents
|
||||
// accordingly.
|
||||
const address REQUESTED_BASE = (address)0x10000000;
|
||||
intx delta = REQUESTED_BASE - actual_base;
|
||||
|
||||
address requested_addr = dumptime_addr + delta;
|
||||
assert(REQUESTED_BASE != 0 && requested_addr != NULL, "sanity");
|
||||
return requested_addr;
|
||||
}
|
||||
|
||||
ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
|
||||
size_t num_bits = region.byte_size() / (UseCompressedOops ? sizeof(narrowOop) : sizeof(oop));
|
||||
ResourceBitMap oopmap(num_bits);
|
||||
|
@ -1619,7 +1656,7 @@ ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
|
|||
++ num_objs;
|
||||
}
|
||||
|
||||
log_info(cds, heap)("calculate_oopmap: objects = %6d, embedded oops = %7d, nulls = %7d",
|
||||
log_info(cds, heap)("calculate_oopmap: objects = %6d, oop fields = %7d (nulls = %7d)",
|
||||
num_objs, finder.num_total_oops(), finder.num_null_oops());
|
||||
return oopmap;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "oops/oopHandle.hpp"
|
||||
#include "oops/oopsHierarchy.hpp"
|
||||
#include "oops/typeArrayKlass.hpp"
|
||||
#include "utilities/bitMap.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
|
@ -517,6 +518,13 @@ private:
|
|||
static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static bool initialize_enum_klass(InstanceKlass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
|
||||
// Returns the address of a heap object when it's mapped at the
|
||||
// runtime requested address. See comments in archiveBuilder.hpp.
|
||||
static address to_requested_address(address dumptime_addr) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
|
||||
static oop to_requested_address(oop dumptime_oop) {
|
||||
return cast_to_oop(to_requested_address(cast_from_oop<address>(dumptime_oop)));
|
||||
}
|
||||
};
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
|
|
Загрузка…
Ссылка в новой задаче