Skip to content

Commit 581f90e

Browse files
committed
8311604: Simplify NOCOOPS requested addresses for archived heap objects
Reviewed-by: ccheung
1 parent 4a1fcb6 commit 581f90e

30 files changed

+231
-244
lines changed

src/hotspot/share/cds/archiveBuilder.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
10341034

10351035
#if INCLUDE_CDS_JAVA_HEAP
10361036
static void log_heap_region(ArchiveHeapInfo* heap_info) {
1037-
MemRegion r = heap_info->memregion();
1037+
MemRegion r = heap_info->buffer_region();
10381038
address start = address(r.start());
10391039
address end = address(r.end());
10401040
log_region("heap", start, end, to_requested(start));
@@ -1204,8 +1204,8 @@ void ArchiveBuilder::print_bitmap_region_stats(size_t size, size_t total_size) {
12041204
}
12051205

12061206
void ArchiveBuilder::print_heap_region_stats(ArchiveHeapInfo *info, size_t total_size) {
1207-
char* start = info->start();
1208-
size_t size = info->byte_size();
1207+
char* start = info->buffer_start();
1208+
size_t size = info->buffer_byte_size();
12091209
char* top = start + size;
12101210
log_debug(cds)("hp space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used] at " INTPTR_FORMAT,
12111211
size, size/double(total_size)*100.0, size, p2i(start));

src/hotspot/share/cds/archiveHeapLoader.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,20 @@ intx ArchiveHeapLoader::_runtime_offset = 0;
5454
bool ArchiveHeapLoader::_loading_failed = false;
5555

5656
// Support for mapped heap.
57+
uintptr_t ArchiveHeapLoader::_mapped_heap_bottom = 0;
5758
bool ArchiveHeapLoader::_mapped_heap_relocation_initialized = false;
5859
ptrdiff_t ArchiveHeapLoader::_mapped_heap_delta = 0;
5960

6061
// Every mapped region is offset by _mapped_heap_delta from its requested address.
6162
// See FileMapInfo::heap_region_requested_address().
62-
void ArchiveHeapLoader::init_mapped_heap_relocation(ptrdiff_t delta, int dumptime_oop_shift) {
63+
void ArchiveHeapLoader::init_mapped_heap_info(address mapped_heap_bottom, ptrdiff_t delta, int dumptime_oop_shift) {
6364
assert(!_mapped_heap_relocation_initialized, "only once");
6465
if (!UseCompressedOops) {
6566
assert(dumptime_oop_shift == 0, "sanity");
6667
}
6768
assert(can_map(), "sanity");
6869
init_narrow_oop_decoding(CompressedOops::base() + delta, dumptime_oop_shift);
70+
_mapped_heap_bottom = (intptr_t)mapped_heap_bottom;
6971
_mapped_heap_delta = delta;
7072
_mapped_heap_relocation_initialized = true;
7173
}
@@ -374,6 +376,9 @@ void ArchiveHeapLoader::finish_initialization() {
374376
}
375377
if (is_in_use()) {
376378
patch_native_pointers();
379+
intptr_t bottom = is_loaded() ? _loaded_heap_bottom : _mapped_heap_bottom;
380+
intptr_t roots_oop = bottom + FileMapInfo::current_info()->heap_roots_offset();
381+
HeapShared::init_roots(cast_to_oop(roots_oop));
377382
}
378383
}
379384

src/hotspot/share/cds/archiveHeapLoader.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class ArchiveHeapLoader : AllStatic {
102102
static void fixup_region() NOT_CDS_JAVA_HEAP_RETURN;
103103

104104
#if INCLUDE_CDS_JAVA_HEAP
105-
static void init_mapped_heap_relocation(ptrdiff_t delta, int dumptime_oop_shift);
105+
static void init_mapped_heap_info(address mapped_heap_bottom, ptrdiff_t delta, int dumptime_oop_shift);
106106
private:
107107
static bool _is_mapped;
108108
static bool _is_loaded;
@@ -124,6 +124,7 @@ class ArchiveHeapLoader : AllStatic {
124124

125125
// is_mapped() only: the mapped address of each region is offset by this amount from
126126
// their requested address.
127+
static uintptr_t _mapped_heap_bottom;
127128
static ptrdiff_t _mapped_heap_delta;
128129
static bool _mapped_heap_relocation_initialized;
129130

src/hotspot/share/cds/archiveHeapWriter.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@
4747

4848
#if INCLUDE_CDS_JAVA_HEAP
4949

50-
GrowableArrayCHeap<u1, mtClassShared>* ArchiveHeapWriter::_buffer;
50+
GrowableArrayCHeap<u1, mtClassShared>* ArchiveHeapWriter::_buffer = nullptr;
5151

5252
// The following are offsets from buffer_bottom()
5353
size_t ArchiveHeapWriter::_buffer_used;
54-
size_t ArchiveHeapWriter::_heap_roots_bottom_offset;
54+
size_t ArchiveHeapWriter::_heap_roots_offset;
5555

5656
size_t ArchiveHeapWriter::_heap_roots_word_size;
5757

@@ -153,7 +153,7 @@ address ArchiveHeapWriter::buffered_addr_to_requested_addr(address buffered_addr
153153
}
154154

155155
oop ArchiveHeapWriter::heap_roots_requested_address() {
156-
return cast_to_oop(_requested_bottom + _heap_roots_bottom_offset);
156+
return cast_to_oop(_requested_bottom + _heap_roots_offset);
157157
}
158158

159159
address ArchiveHeapWriter::requested_address() {
@@ -213,7 +213,7 @@ void ArchiveHeapWriter::copy_roots_to_buffer(GrowableArrayCHeap<oop, mtClassShar
213213
}
214214
log_info(cds, heap)("archived obj roots[%d] = " SIZE_FORMAT " bytes, klass = %p, obj = %p", length, byte_size, k, mem);
215215

216-
_heap_roots_bottom_offset = _buffer_used;
216+
_heap_roots_offset = _buffer_used;
217217
_buffer_used = new_used;
218218
}
219219

@@ -339,13 +339,25 @@ void ArchiveHeapWriter::set_requested_address(ArchiveHeapInfo* info) {
339339
size_t heap_region_byte_size = _buffer_used;
340340
assert(heap_region_byte_size > 0, "must archived at least one object!");
341341

342-
_requested_bottom = align_down(heap_end - heap_region_byte_size, HeapRegion::GrainBytes);
342+
343+
if (UseCompressedOops) {
344+
_requested_bottom = align_down(heap_end - heap_region_byte_size, HeapRegion::GrainBytes);
345+
} else {
346+
// We always write the objects as if the heap started at this address. This
347+
// makes the contents of the archive heap deterministic.
348+
//
349+
// Note that at runtime, the heap address is selected by the OS, so the archive
350+
// heap will not be mapped at 0x10000000, and the contents need to be patched.
351+
_requested_bottom = (address)NOCOOPS_REQUESTED_BASE;
352+
}
353+
343354
assert(is_aligned(_requested_bottom, HeapRegion::GrainBytes), "sanity");
344355

345356
_requested_top = _requested_bottom + _buffer_used;
346357

347-
info->set_memregion(MemRegion(offset_to_buffered_address<HeapWord*>(0),
348-
offset_to_buffered_address<HeapWord*>(_buffer_used)));
358+
info->set_buffer_region(MemRegion(offset_to_buffered_address<HeapWord*>(0),
359+
offset_to_buffered_address<HeapWord*>(_buffer_used)));
360+
info->set_heap_roots_offset(_heap_roots_offset);
349361
}
350362

351363
// Oop relocation
@@ -371,14 +383,11 @@ template <typename T> void ArchiveHeapWriter::store_requested_oop_in_buffer(T* b
371383
store_oop_in_buffer(buffered_addr, request_oop);
372384
}
373385

374-
void ArchiveHeapWriter::store_oop_in_buffer(oop* buffered_addr, oop requested_obj) {
375-
// Make heap content deterministic. See comments inside HeapShared::to_requested_address.
376-
*buffered_addr = HeapShared::to_requested_address(requested_obj);
386+
inline void ArchiveHeapWriter::store_oop_in_buffer(oop* buffered_addr, oop requested_obj) {
387+
*buffered_addr = requested_obj;
377388
}
378389

379-
void ArchiveHeapWriter::store_oop_in_buffer(narrowOop* buffered_addr, oop requested_obj) {
380-
// Note: HeapShared::to_requested_address() is not necessary because
381-
// the heap always starts at a deterministic address with UseCompressedOops==true.
390+
inline void ArchiveHeapWriter::store_oop_in_buffer(narrowOop* buffered_addr, oop requested_obj) {
382391
narrowOop val = CompressedOops::encode_not_null(requested_obj);
383392
*buffered_addr = val;
384393
}
@@ -481,7 +490,7 @@ void ArchiveHeapWriter::relocate_embedded_oops(GrowableArrayCHeap<oop, mtClassSh
481490

482491
// Relocate HeapShared::roots(), which is created in copy_roots_to_buffer() and
483492
// doesn't have a corresponding src_obj, so we can't use EmbeddedOopRelocator on it.
484-
oop requested_roots = requested_obj_from_buffer_offset(_heap_roots_bottom_offset);
493+
oop requested_roots = requested_obj_from_buffer_offset(_heap_roots_offset);
485494
update_header_for_requested_obj(requested_roots, nullptr, Universe::objectArrayKlassObj());
486495
int length = roots != nullptr ? roots->length() : 0;
487496
for (int i = 0; i < length; i++) {

src/hotspot/share/cds/archiveHeapWriter.hpp

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,81 @@
3838
class MemRegion;
3939

4040
class ArchiveHeapInfo {
41-
MemRegion _memregion;
41+
MemRegion _buffer_region; // Contains the archived objects to be written into the CDS archive.
4242
CHeapBitMap _oopmap;
4343
CHeapBitMap _ptrmap;
44+
size_t _heap_roots_offset; // Offset of the HeapShared::roots() object, from the bottom
45+
// of the archived heap objects, in bytes.
4446

4547
public:
46-
ArchiveHeapInfo() : _memregion(), _oopmap(128, mtClassShared), _ptrmap(128, mtClassShared) {}
47-
bool is_used() { return !_memregion.is_empty(); }
48+
ArchiveHeapInfo() : _buffer_region(), _oopmap(128, mtClassShared), _ptrmap(128, mtClassShared) {}
49+
bool is_used() { return !_buffer_region.is_empty(); }
4850

49-
MemRegion memregion() { return _memregion; }
50-
void set_memregion(MemRegion r) { _memregion = r; }
51+
MemRegion buffer_region() { return _buffer_region; }
52+
void set_buffer_region(MemRegion r) { _buffer_region = r; }
5153

52-
char* start() { return (char*)_memregion.start(); }
53-
size_t byte_size() { return _memregion.byte_size(); }
54+
char* buffer_start() { return (char*)_buffer_region.start(); }
55+
size_t buffer_byte_size() { return _buffer_region.byte_size(); }
5456

5557
CHeapBitMap* oopmap() { return &_oopmap; }
5658
CHeapBitMap* ptrmap() { return &_ptrmap; }
59+
60+
void set_heap_roots_offset(size_t n) { _heap_roots_offset = n; }
61+
size_t heap_roots_offset() const { return _heap_roots_offset; }
5762
};
5863

5964
#if INCLUDE_CDS_JAVA_HEAP
6065
class ArchiveHeapWriter : AllStatic {
66+
// ArchiveHeapWriter manipulates three types of addresses:
67+
//
68+
// "source" vs "buffered" vs "requested"
69+
//
70+
// (Note: the design and convention is the same as for the archiving of Metaspace objects.
71+
// See archiveBuilder.hpp.)
72+
//
73+
// - "source objects" are regular Java objects allocated during the execution
74+
// of "java -Xshare:dump". They can be used as regular oops.
75+
//
76+
// HeapShared::archive_objects() recursively searches for the oops that need to be
77+
// stored into the CDS archive. These are entered into HeapShared::archived_object_cache().
78+
//
79+
// - "buffered objects" are copies of the "source objects", and are stored in into
80+
// ArchiveHeapWriter::_buffer, which is a GrowableArray that sits outside of
81+
// the valid heap range. Therefore we avoid using the addresses of these copies
82+
// as oops. They are usually called "buffered_addr" in the code (of the type "address").
83+
//
84+
// The buffered objects are stored contiguously, possibly with interleaving fillers
85+
// to make sure no objects span across boundaries of MIN_GC_REGION_ALIGNMENT.
86+
//
87+
// - Each archived object has a "requested address" -- at run time, if the object
88+
// can be mapped at this address, we can avoid relocation.
89+
//
90+
// The requested address is implemented differently depending on UseCompressedOops:
91+
//
92+
// UseCompressedOops == true:
93+
// The archived objects are stored assuming that the runtime COOPS compression
94+
// scheme is exactly the same as in dump time (or else a more expensive runtime relocation
95+
// would be needed.)
96+
//
97+
// At dump time, we assume that the runtime heap range is exactly the same as
98+
// in dump time. The requested addresses of the archived objects are chosen such that
99+
// they would occupy the top end of a G1 heap (TBD when dumping is supported by other
100+
// collectors. See JDK-8298614).
101+
//
102+
// UseCompressedOops == false:
103+
// At runtime, the heap range is usually picked (randomly) by the OS, so we will almost always
104+
// need to perform relocation. Hence, the goal of the "requested address" is to ensure that
105+
// the contents of the archived objects are deterministic. I.e., the oop fields of archived
106+
// objects will always point to deterministic addresses.
107+
//
108+
// For G1, the archived heap is written such that the lowest archived object is placed
109+
// at NOCOOPS_REQUESTED_BASE. (TBD after JDK-8298614).
110+
// ----------------------------------------------------------------------
111+
112+
public:
113+
static const intptr_t NOCOOPS_REQUESTED_BASE = 0x10000000;
114+
115+
private:
61116
class EmbeddedOopRelocator;
62117
struct NativePointerInfo {
63118
oop _src_obj;
@@ -70,30 +125,13 @@ class ArchiveHeapWriter : AllStatic {
70125
// (TODO: Perhaps change to 256K to be compatible with Shenandoah)
71126
static constexpr int MIN_GC_REGION_ALIGNMENT = 1 * M;
72127

73-
// "source" vs "buffered" vs "requested"
74-
//
75-
// [1] HeapShared::archive_objects() identifies all of the oops that need to be stored
76-
// into the CDS archive. These are entered into HeapShared::archived_object_cache().
77-
// These are called "source objects"
78-
//
79-
// [2] ArchiveHeapWriter::write() copies all source objects into ArchiveHeapWriter::_buffer,
80-
// which is a GrowableArray that sites outside of the valid heap range. Therefore
81-
// we avoid using the addresses of these copies as oops. They are usually
82-
// called "buffered_addr" in the code (of the type "address").
83-
//
84-
// [3] Each archived object has a "requested address" -- at run time, if the object
85-
// can be mapped at this address, we can avoid relocation.
86-
//
87-
// Note: the design and convention is the same as for the archiving of Metaspace objects.
88-
// See archiveBuilder.hpp.
89-
90128
static GrowableArrayCHeap<u1, mtClassShared>* _buffer;
91129

92130
// The number of bytes that have written into _buffer (may be smaller than _buffer->length()).
93131
static size_t _buffer_used;
94132

95133
// The bottom of the copy of Heap::roots() inside this->_buffer.
96-
static size_t _heap_roots_bottom_offset;
134+
static size_t _heap_roots_offset;
97135
static size_t _heap_roots_word_size;
98136

99137
// The address range of the requested location of the archived heap objects.
@@ -160,8 +198,8 @@ class ArchiveHeapWriter : AllStatic {
160198

161199
static oop load_oop_from_buffer(oop* buffered_addr);
162200
static oop load_oop_from_buffer(narrowOop* buffered_addr);
163-
static void store_oop_in_buffer(oop* buffered_addr, oop requested_obj);
164-
static void store_oop_in_buffer(narrowOop* buffered_addr, oop requested_obj);
201+
inline static void store_oop_in_buffer(oop* buffered_addr, oop requested_obj);
202+
inline static void store_oop_in_buffer(narrowOop* buffered_addr, oop requested_obj);
165203

166204
template <typename T> static oop load_source_oop_from_buffer(T* buffered_addr);
167205
template <typename T> static void store_requested_oop_in_buffer(T* buffered_addr, oop request_oop);
@@ -182,7 +220,7 @@ class ArchiveHeapWriter : AllStatic {
182220
static address requested_address(); // requested address of the lowest achived heap object
183221
static oop heap_roots_requested_address(); // requested address of HeapShared::roots()
184222
static address buffered_heap_roots_addr() {
185-
return offset_to_buffered_address<address>(_heap_roots_bottom_offset);
223+
return offset_to_buffered_address<address>(_heap_roots_offset);
186224
}
187225
static size_t heap_roots_word_size() {
188226
return _heap_roots_word_size;

src/hotspot/share/cds/archiveUtils.cpp

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -277,21 +277,6 @@ void WriteClosure::do_ptr(void** p) {
277277
_dump_region->append_intptr_t((intptr_t)ptr, true);
278278
}
279279

280-
void WriteClosure::do_oop(oop* o) {
281-
if (*o == nullptr) {
282-
_dump_region->append_intptr_t(0);
283-
} else {
284-
assert(HeapShared::can_write(), "sanity");
285-
intptr_t p;
286-
if (UseCompressedOops) {
287-
p = (intptr_t)CompressedOops::encode_not_null(*o);
288-
} else {
289-
p = cast_from_oop<intptr_t>(HeapShared::to_requested_address(*o));
290-
}
291-
_dump_region->append_intptr_t(p);
292-
}
293-
}
294-
295280
void WriteClosure::do_region(u_char* start, size_t size) {
296281
assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");
297282
assert(size % sizeof(intptr_t) == 0, "bad size");
@@ -334,28 +319,6 @@ void ReadClosure::do_tag(int tag) {
334319
FileMapInfo::assert_mark(tag == old_tag);
335320
}
336321

337-
void ReadClosure::do_oop(oop *p) {
338-
if (UseCompressedOops) {
339-
narrowOop o = CompressedOops::narrow_oop_cast(nextPtr());
340-
if (CompressedOops::is_null(o) || !ArchiveHeapLoader::is_in_use()) {
341-
*p = nullptr;
342-
} else {
343-
assert(ArchiveHeapLoader::can_use(), "sanity");
344-
assert(ArchiveHeapLoader::is_in_use(), "must be");
345-
*p = ArchiveHeapLoader::decode_from_archive(o);
346-
}
347-
} else {
348-
intptr_t dumptime_oop = nextPtr();
349-
if (dumptime_oop == 0 || !ArchiveHeapLoader::is_in_use()) {
350-
*p = nullptr;
351-
} else {
352-
assert(!ArchiveHeapLoader::is_loaded(), "ArchiveHeapLoader::can_load() is not supported for uncompessed oops");
353-
intptr_t runtime_oop = dumptime_oop + ArchiveHeapLoader::mapped_heap_delta();
354-
*p = cast_to_oop(runtime_oop);
355-
}
356-
}
357-
}
358-
359322
void ReadClosure::do_region(u_char* start, size_t size) {
360323
assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");
361324
assert(size % sizeof(intptr_t) == 0, "bad size");

src/hotspot/share/cds/archiveUtils.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
#ifndef SHARE_CDS_ARCHIVEUTILS_HPP
2626
#define SHARE_CDS_ARCHIVEUTILS_HPP
2727

28+
#include "cds/serializeClosure.hpp"
2829
#include "logging/log.hpp"
29-
#include "memory/iterator.hpp"
3030
#include "memory/virtualspace.hpp"
3131
#include "utilities/bitMap.hpp"
3232
#include "utilities/exceptions.hpp"
@@ -202,7 +202,6 @@ class WriteClosure : public SerializeClosure {
202202
_dump_region->append_intptr_t((intptr_t)tag);
203203
}
204204

205-
void do_oop(oop* o);
206205
void do_region(u_char* start, size_t size);
207206
bool reading() const { return false; }
208207
};
@@ -226,7 +225,6 @@ class ReadClosure : public SerializeClosure {
226225
void do_int(int* p);
227226
void do_bool(bool *p);
228227
void do_tag(int tag);
229-
void do_oop(oop *p);
230228
void do_region(u_char* start, size_t size);
231229
bool reading() const { return true; }
232230
};

src/hotspot/share/cds/cdsHeapVerifier.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
*
2323
*/
2424

25-
#ifndef SHARED_CDS_CDSHEAPVERIFIER_HPP
26-
#define SHARED_CDS_CDSHEAPVERIFIER_HPP
25+
#ifndef SHARE_CDS_CDSHEAPVERIFIER_HPP
26+
#define SHARE_CDS_CDSHEAPVERIFIER_HPP
2727

2828
#include "cds/heapShared.hpp"
2929
#include "memory/iterator.hpp"
@@ -88,4 +88,4 @@ class CDSHeapVerifier : public KlassClosure {
8888
};
8989

9090
#endif // INCLUDE_CDS_JAVA_HEAP
91-
#endif // SHARED_CDS_CDSHEAPVERIFIER_HPP
91+
#endif // SHARE_CDS_CDSHEAPVERIFIER_HPP

0 commit comments

Comments
 (0)