Skip to content

Commit 0616648

Browse files
committedJul 5, 2023
8311035: CDS should not use dump time JVM narrow Klass encoding to pre-compute Klass ids
Reviewed-by: iklam
1 parent 6eba096 commit 0616648

8 files changed

+102
-89
lines changed
 

‎src/hotspot/share/cds/archiveBuilder.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -809,12 +809,16 @@ uintx ArchiveBuilder::any_to_offset(address p) const {
809809
return buffer_to_offset(p);
810810
}
811811

812+
#if INCLUDE_CDS_JAVA_HEAP
812813
narrowKlass ArchiveBuilder::get_requested_narrow_klass(Klass* k) {
813814
assert(DumpSharedSpaces, "sanity");
814815
k = get_buffered_klass(k);
815816
Klass* requested_k = to_requested(k);
816-
return CompressedKlassPointers::encode_not_null(requested_k, _requested_static_archive_bottom);
817+
address narrow_klass_base = _requested_static_archive_bottom; // runtime encoding base == runtime mapping start
818+
const int narrow_klass_shift = ArchiveHeapWriter::precomputed_narrow_klass_shift;
819+
return CompressedKlassPointers::encode_not_null(requested_k, narrow_klass_base, narrow_klass_shift);
817820
}
821+
#endif // INCLUDE_CDS_JAVA_HEAP
818822

819823
// RelocateBufferToRequested --- Relocate all the pointers in rw/ro,
820824
// so that the archive can be mapped to the "requested" location without runtime relocation.

‎src/hotspot/share/cds/archiveHeapWriter.hpp

+12
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,18 @@ class ArchiveHeapWriter : AllStatic {
192192
static oop source_obj_to_requested_obj(oop src_obj);
193193
static oop buffered_addr_to_source_obj(address buffered_addr);
194194
static address buffered_addr_to_requested_addr(address buffered_addr);
195+
196+
// Archived heap object headers carry pre-computed narrow Klass ids calculated with the
197+
// following scheme:
198+
// 1) the encoding base must be the mapping start address.
199+
// 2) shift must be large enough to result in an encoding range that covers the runtime Klass range.
200+
// That Klass range is defined by CDS archive size and runtime class space size. Luckily, the maximum
201+
// size can be predicted: archive size is assumed to be <1G, class space size capped at 3G, and at
202+
// runtime we put both regions adjacent to each other. Therefore, runtime Klass range size < 4G.
203+
// Since nKlass itself is 32 bit, our encoding range len is 4G, and since we set the base directly
204+
// at mapping start, these 4G are enough. Therefore, we don't need to shift at all (shift=0).
205+
static constexpr int precomputed_narrow_klass_shift = 0;
206+
195207
};
196208
#endif // INCLUDE_CDS_JAVA_HEAP
197209
#endif // SHARE_CDS_ARCHIVEHEAPWRITER_HPP

‎src/hotspot/share/cds/filemap.cpp

+14-9
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment,
222222
_compressed_oops = UseCompressedOops;
223223
_compressed_class_ptrs = UseCompressedClassPointers;
224224
_max_heap_size = MaxHeapSize;
225-
_narrow_klass_shift = CompressedKlassPointers::shift();
226225
_use_optimized_module_handling = MetaspaceShared::use_optimized_module_handling();
227226
_use_full_module_graph = MetaspaceShared::use_full_module_graph();
228227

@@ -283,7 +282,6 @@ void FileMapHeader::print(outputStream* st) {
283282
st->print_cr("- compact_strings: %d", _compact_strings);
284283
st->print_cr("- max_heap_size: " UINTX_FORMAT, _max_heap_size);
285284
st->print_cr("- narrow_oop_mode: %d", _narrow_oop_mode);
286-
st->print_cr("- narrow_klass_shift: %d", _narrow_klass_shift);
287285
st->print_cr("- compressed_oops: %d", _compressed_oops);
288286
st->print_cr("- compressed_class_ptrs: %d", _compressed_class_ptrs);
289287
st->print_cr("- cloned_vtables_offset: " SIZE_FORMAT_X, _cloned_vtables_offset);
@@ -2016,10 +2014,17 @@ bool FileMapInfo::can_use_heap_region() {
20162014
// referenced objects are replaced. See HeapShared::initialize_from_archived_subgraph().
20172015
}
20182016

2017+
// We pre-compute narrow Klass IDs with the runtime mapping start intended to be the base, and a shift of
2018+
// ArchiveHeapWriter::precomputed_narrow_klass_shift. We enforce this encoding at runtime (see
2019+
// CompressedKlassPointers::initialize_for_given_encoding()). Therefore, the following assertions must
2020+
// hold:
2021+
address archive_narrow_klass_base = (address)header()->mapped_base_address();
2022+
const int archive_narrow_klass_shift = ArchiveHeapWriter::precomputed_narrow_klass_shift;
2023+
20192024
log_info(cds)("CDS archive was created with max heap size = " SIZE_FORMAT "M, and the following configuration:",
20202025
max_heap_size()/M);
2021-
log_info(cds)(" narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
2022-
p2i(narrow_klass_base()), narrow_klass_shift());
2026+
log_info(cds)(" narrow_klass_base at mapping start address, narrow_klass_shift = %d",
2027+
archive_narrow_klass_shift);
20232028
log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
20242029
narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
20252030
log_info(cds)(" heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
@@ -2037,11 +2042,11 @@ bool FileMapInfo::can_use_heap_region() {
20372042
UseCompressedOops ? p2i(CompressedOops::end()) :
20382043
UseG1GC ? p2i((address)G1CollectedHeap::heap()->reserved().end()) : 0L);
20392044

2040-
if (narrow_klass_base() != CompressedKlassPointers::base() ||
2041-
narrow_klass_shift() != CompressedKlassPointers::shift()) {
2042-
log_info(cds)("CDS heap data cannot be used because the archive was created with an incompatible narrow klass encoding mode.");
2043-
return false;
2044-
}
2045+
assert(archive_narrow_klass_base == CompressedKlassPointers::base(), "Unexpected encoding base encountered "
2046+
"(" PTR_FORMAT ", expected " PTR_FORMAT ")", p2i(CompressedKlassPointers::base()), p2i(archive_narrow_klass_base));
2047+
assert(archive_narrow_klass_shift == CompressedKlassPointers::shift(), "Unexpected encoding shift encountered "
2048+
"(%d, expected %d)", CompressedKlassPointers::shift(), archive_narrow_klass_shift);
2049+
20452050
return true;
20462051
}
20472052

‎src/hotspot/share/cds/filemap.hpp

-5
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,6 @@ class FileMapHeader: private CDSFileMapHeaderBase {
194194
bool _compact_strings; // value of CompactStrings
195195
uintx _max_heap_size; // java max heap size during dumping
196196
CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode
197-
int _narrow_klass_shift; // save narrow klass base and shift
198197
bool _compressed_oops; // save the flag UseCompressedOops
199198
bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers
200199
size_t _cloned_vtables_offset; // The address of the first cloned vtable
@@ -262,8 +261,6 @@ class FileMapHeader: private CDSFileMapHeaderBase {
262261
bool compact_strings() const { return _compact_strings; }
263262
uintx max_heap_size() const { return _max_heap_size; }
264263
CompressedOops::Mode narrow_oop_mode() const { return _narrow_oop_mode; }
265-
int narrow_klass_shift() const { return _narrow_klass_shift; }
266-
address narrow_klass_base() const { return (address)mapped_base_address(); }
267264
char* cloned_vtables() const { return from_mapped_offset(_cloned_vtables_offset); }
268265
char* serialized_data() const { return from_mapped_offset(_serialized_data_offset); }
269266
address heap_begin() const { return _heap_begin; }
@@ -382,8 +379,6 @@ class FileMapInfo : public CHeapObj<mtInternal> {
382379
address narrow_oop_base() const { return header()->narrow_oop_base(); }
383380
int narrow_oop_shift() const { return header()->narrow_oop_shift(); }
384381
uintx max_heap_size() const { return header()->max_heap_size(); }
385-
address narrow_klass_base() const { return header()->narrow_klass_base(); }
386-
int narrow_klass_shift() const { return header()->narrow_klass_shift(); }
387382
size_t core_region_alignment() const { return header()->core_region_alignment(); }
388383

389384
CompressedOops::Mode narrow_oop_mode() const { return header()->narrow_oop_mode(); }

‎src/hotspot/share/cds/metaspaceShared.cpp

+16-4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#include "oops/oopHandle.hpp"
7070
#include "prims/jvmtiExport.hpp"
7171
#include "runtime/arguments.hpp"
72+
#include "runtime/globals.hpp"
7273
#include "runtime/globals_extension.hpp"
7374
#include "runtime/handles.inline.hpp"
7475
#include "runtime/os.inline.hpp"
@@ -1136,7 +1137,7 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File
11361137

11371138
if (result == MAP_ARCHIVE_SUCCESS) {
11381139
SharedBaseAddress = (size_t)mapped_base_address;
1139-
LP64_ONLY({
1140+
#ifdef _LP64
11401141
if (Metaspace::using_class_space()) {
11411142
// Set up ccs in metaspace.
11421143
Metaspace::initialize_class_space(class_space_rs);
@@ -1146,13 +1147,24 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File
11461147
address cds_base = (address)static_mapinfo->mapped_base();
11471148
address ccs_end = (address)class_space_rs.end();
11481149
assert(ccs_end > cds_base, "Sanity check");
1149-
CompressedKlassPointers::initialize(cds_base, ccs_end - cds_base);
1150-
1150+
#if INCLUDE_CDS_JAVA_HEAP
1151+
// We archived objects with pre-computed narrow Klass id. Set up encoding such that these Ids stay valid.
1152+
address precomputed_narrow_klass_base = cds_base;
1153+
const int precomputed_narrow_klass_shift = ArchiveHeapWriter::precomputed_narrow_klass_shift;
1154+
CompressedKlassPointers::initialize_for_given_encoding(
1155+
cds_base, ccs_end - cds_base, // Klass range
1156+
precomputed_narrow_klass_base, precomputed_narrow_klass_shift // precomputed encoding, see ArchiveHeapWriter
1157+
);
1158+
#else
1159+
CompressedKlassPointers::initialize (
1160+
cds_base, ccs_end - cds_base // Klass range
1161+
);
1162+
#endif // INCLUDE_CDS_JAVA_HEAP
11511163
// map_or_load_heap_region() compares the current narrow oop and klass encodings
11521164
// with the archived ones, so it must be done after all encodings are determined.
11531165
static_mapinfo->map_or_load_heap_region();
11541166
}
1155-
});
1167+
#endif // _LP64
11561168
log_info(cds)("optimized module handling: %s", MetaspaceShared::use_optimized_module_handling() ? "enabled" : "disabled");
11571169
log_info(cds)("full module graph: %s", MetaspaceShared::use_full_module_graph() ? "enabled" : "disabled");
11581170
} else {

‎src/hotspot/share/oops/compressedOops.cpp

+36-54
Original file line numberDiff line numberDiff line change
@@ -186,83 +186,63 @@ NarrowPtrStruct CompressedKlassPointers::_narrow_klass = { nullptr, 0, true };
186186
// are compiled for 32bit to LP64_ONLY).
187187
size_t CompressedKlassPointers::_range = 0;
188188

189+
#ifdef _LP64
190+
191+
// Given a klass range [addr, addr+len) and a given encoding scheme, assert that this scheme covers the range, then
192+
// set this encoding scheme. Used by CDS at runtime to re-instate the scheme used to pre-compute klass ids for
193+
// archived heap objects.
194+
void CompressedKlassPointers::initialize_for_given_encoding(address addr, size_t len, address requested_base, int requested_shift) {
195+
assert(is_valid_base(requested_base), "Address must be a valid encoding base");
196+
address const end = addr + len;
197+
198+
const int narrow_klasspointer_bits = sizeof(narrowKlass) * 8;
199+
const size_t encoding_range_size = nth_bit(narrow_klasspointer_bits + requested_shift);
200+
address encoding_range_end = requested_base + encoding_range_size;
201+
202+
// Note: it would be technically valid for the encoding base to precede the start of the Klass range. But we only call
203+
// this function from CDS, and therefore know this to be true.
204+
assert(requested_base == addr, "Invalid requested base");
205+
assert(encoding_range_end >= end, "Encoding does not cover the full Klass range");
206+
207+
set_base(requested_base);
208+
set_shift(requested_shift);
209+
set_range(encoding_range_size);
210+
}
189211

190212
// Given an address range [addr, addr+len) which the encoding is supposed to
191213
// cover, choose base, shift and range.
192214
// The address range is the expected range of uncompressed Klass pointers we
193215
// will encounter (and the implicit promise that there will be no Klass
194216
// structures outside this range).
195217
void CompressedKlassPointers::initialize(address addr, size_t len) {
196-
#ifdef _LP64
197218
assert(is_valid_base(addr), "Address must be a valid encoding base");
198219
address const end = addr + len;
199220

200221
address base;
201222
int shift;
202223
size_t range;
203224

204-
if (UseSharedSpaces || DumpSharedSpaces) {
205-
206-
// Special requirements if CDS is active:
207-
// Encoding base and shift must be the same between dump and run time.
208-
// CDS takes care that the SharedBaseAddress and CompressedClassSpaceSize
209-
// are the same. Archive size will be probably different at runtime, but
210-
// it can only be smaller than at, never larger, since archives get
211-
// shrunk at the end of the dump process.
212-
// From that it follows that the range [addr, len) we are handed in at
213-
// runtime will start at the same address then at dumptime, and its len
214-
// may be smaller at runtime then it was at dump time.
215-
//
216-
// To be very careful here, we avoid any optimizations and just keep using
217-
// the same address and shift value. Specifically we avoid using zero-based
218-
// encoding. We also set the expected value range to 4G (encoding range
219-
// cannot be larger than that).
220-
225+
// Attempt to run with encoding base == zero
226+
if (end <= (address)KlassEncodingMetaspaceMax) {
227+
base = 0;
228+
} else {
221229
base = addr;
230+
}
222231

223-
// JDK-8265705
224-
// This is a temporary fix for aarch64: there, if the range-to-be-encoded is located
225-
// below 32g, either encoding base should be zero or base should be aligned to 4G
226-
// and shift should be zero. The simplest way to fix this for now is to force
227-
// shift to zero for both runtime and dumptime.
228-
// Note however that this is not a perfect solution. Ideally this whole function
229-
// should be CDS agnostic, that would simplify it - and testing - a lot. See JDK-8267141
230-
// for details.
231-
shift = 0;
232-
233-
// This must be true since at dumptime cds+ccs is 4G, at runtime it can
234-
// only be smaller, see comment above.
235-
assert(len <= 4 * G, "Encoding range cannot be larger than 4G");
236-
range = 4 * G;
232+
// Highest offset a Klass* can ever have in relation to base.
233+
range = end - base;
237234

235+
// We may not even need a shift if the range fits into 32bit:
236+
const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1);
237+
if (range < UnscaledClassSpaceMax) {
238+
shift = 0;
238239
} else {
239-
240-
// Otherwise we attempt to use a zero base if the range fits in lower 32G.
241-
if (end <= (address)KlassEncodingMetaspaceMax) {
242-
base = 0;
243-
} else {
244-
base = addr;
245-
}
246-
247-
// Highest offset a Klass* can ever have in relation to base.
248-
range = end - base;
249-
250-
// We may not even need a shift if the range fits into 32bit:
251-
const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1);
252-
if (range < UnscaledClassSpaceMax) {
253-
shift = 0;
254-
} else {
255-
shift = LogKlassAlignmentInBytes;
256-
}
257-
240+
shift = LogKlassAlignmentInBytes;
258241
}
259242

260243
set_base(base);
261244
set_shift(shift);
262245
set_range(range);
263-
#else
264-
fatal("64bit only.");
265-
#endif
266246
}
267247

268248
// Given an address p, return true if p can be used as an encoding base.
@@ -300,3 +280,5 @@ void CompressedKlassPointers::set_range(size_t range) {
300280
assert(UseCompressedClassPointers, "no compressed klass ptrs?");
301281
_range = range;
302282
}
283+
284+
#endif // _LP64

‎src/hotspot/share/oops/compressedOops.hpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,20 @@ class CompressedKlassPointers : public AllStatic {
155155

156156
static void set_base(address base);
157157
static void set_range(size_t range);
158-
159-
public:
160-
161158
static void set_shift(int shift);
162159

160+
public:
163161

164162
// Given an address p, return true if p can be used as an encoding base.
165163
// (Some platforms have restrictions of what constitutes a valid base
166164
// address).
167165
static bool is_valid_base(address p);
168166

167+
// Given a klass range [addr, addr+len) and a given encoding scheme, assert that this scheme covers the range, then
168+
// set this encoding scheme. Used by CDS at runtime to re-instate the scheme used to pre-compute klass ids for
169+
// archived heap objects.
170+
static void initialize_for_given_encoding(address addr, size_t len, address requested_base, int requested_shift);
171+
169172
// Given an address range [addr, addr+len) which the encoding is supposed to
170173
// cover, choose base, shift and range.
171174
// The address range is the expected range of uncompressed Klass pointers we
@@ -182,13 +185,13 @@ class CompressedKlassPointers : public AllStatic {
182185
static bool is_null(Klass* v) { return v == nullptr; }
183186
static bool is_null(narrowKlass v) { return v == 0; }
184187

185-
static inline Klass* decode_raw(narrowKlass v, address base);
188+
static inline Klass* decode_raw(narrowKlass v, address base, int shift);
186189
static inline Klass* decode_raw(narrowKlass v);
187190
static inline Klass* decode_not_null(narrowKlass v);
188-
static inline Klass* decode_not_null(narrowKlass v, address base);
191+
static inline Klass* decode_not_null(narrowKlass v, address base, int shift);
189192
static inline Klass* decode(narrowKlass v);
190193
static inline narrowKlass encode_not_null(Klass* v);
191-
static inline narrowKlass encode_not_null(Klass* v, address base);
194+
static inline narrowKlass encode_not_null(Klass* v, address base, int shift);
192195
static inline narrowKlass encode(Klass* v);
193196

194197
};

‎src/hotspot/share/oops/compressedOops.inline.hpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -123,20 +123,20 @@ static inline bool check_alignment(Klass* v) {
123123
}
124124

125125
inline Klass* CompressedKlassPointers::decode_raw(narrowKlass v) {
126-
return decode_raw(v, base());
126+
return decode_raw(v, base(), shift());
127127
}
128128

129-
inline Klass* CompressedKlassPointers::decode_raw(narrowKlass v, address narrow_base) {
130-
return (Klass*)((uintptr_t)narrow_base +((uintptr_t)v << shift()));
129+
inline Klass* CompressedKlassPointers::decode_raw(narrowKlass v, address narrow_base, int shift) {
130+
return (Klass*)((uintptr_t)narrow_base +((uintptr_t)v << shift));
131131
}
132132

133133
inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v) {
134-
return decode_not_null(v, base());
134+
return decode_not_null(v, base(), shift());
135135
}
136136

137-
inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v, address narrow_base) {
137+
inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v, address narrow_base, int shift) {
138138
assert(!is_null(v), "narrow klass value can never be zero");
139-
Klass* result = decode_raw(v, narrow_base);
139+
Klass* result = decode_raw(v, narrow_base, shift);
140140
assert(check_alignment(result), "address not aligned: " PTR_FORMAT, p2i(result));
141141
return result;
142142
}
@@ -146,17 +146,17 @@ inline Klass* CompressedKlassPointers::decode(narrowKlass v) {
146146
}
147147

148148
inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v) {
149-
return encode_not_null(v, base());
149+
return encode_not_null(v, base(), shift());
150150
}
151151

152-
inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v, address narrow_base) {
152+
inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v, address narrow_base, int shift) {
153153
assert(!is_null(v), "klass value can never be zero");
154154
assert(check_alignment(v), "Address not aligned");
155155
uint64_t pd = (uint64_t)(pointer_delta(v, narrow_base, 1));
156156
assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding");
157-
uint64_t result = pd >> shift();
157+
uint64_t result = pd >> shift;
158158
assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow");
159-
assert(decode_not_null((narrowKlass)result, narrow_base) == v, "reversibility");
159+
assert(decode_not_null((narrowKlass)result, narrow_base, shift) == v, "reversibility");
160160
return (narrowKlass)result;
161161
}
162162

0 commit comments

Comments
 (0)
Please sign in to comment.