1 /* 2 * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "cds/archiveHeapLoader.inline.hpp" 26 #include "cds/cdsConfig.hpp" 27 #include "cds/heapShared.hpp" 28 #include "cds/metaspaceShared.hpp" 29 #include "classfile/classLoaderDataShared.hpp" 30 #include "classfile/systemDictionaryShared.hpp" 31 #include "gc/shared/collectedHeap.hpp" 32 #include "logging/log.hpp" 33 #include "memory/iterator.inline.hpp" 34 #include "memory/resourceArea.hpp" 35 #include "memory/universe.hpp" 36 #include "sanitizers/ub.hpp" 37 #include "utilities/bitMap.inline.hpp" 38 #include "utilities/copy.hpp" 39 40 #if INCLUDE_CDS_JAVA_HEAP 41 42 bool ArchiveHeapLoader::_is_mapped = false; 43 bool ArchiveHeapLoader::_is_loaded = false; 44 45 bool ArchiveHeapLoader::_narrow_oop_base_initialized = false; 46 address ArchiveHeapLoader::_narrow_oop_base; 47 int ArchiveHeapLoader::_narrow_oop_shift; 48 49 // Support for loaded heap. 50 uintptr_t ArchiveHeapLoader::_loaded_heap_bottom = 0; 51 uintptr_t ArchiveHeapLoader::_loaded_heap_top = 0; 52 uintptr_t ArchiveHeapLoader::_dumptime_base = UINTPTR_MAX; 53 uintptr_t ArchiveHeapLoader::_dumptime_top = 0; 54 intx ArchiveHeapLoader::_runtime_offset = 0; 55 bool ArchiveHeapLoader::_loading_failed = false; 56 57 // Support for mapped heap. 58 uintptr_t ArchiveHeapLoader::_mapped_heap_bottom = 0; 59 bool ArchiveHeapLoader::_mapped_heap_relocation_initialized = false; 60 ptrdiff_t ArchiveHeapLoader::_mapped_heap_delta = 0; 61 62 // Every mapped region is offset by _mapped_heap_delta from its requested address. 63 // See FileMapInfo::heap_region_requested_address(). 64 ATTRIBUTE_NO_UBSAN 65 void ArchiveHeapLoader::init_mapped_heap_info(address mapped_heap_bottom, ptrdiff_t delta, int dumptime_oop_shift) { 66 assert(!_mapped_heap_relocation_initialized, "only once"); 67 if (!UseCompressedOops) { 68 assert(dumptime_oop_shift == 0, "sanity"); 69 } 70 assert(can_map(), "sanity"); 71 init_narrow_oop_decoding(CompressedOops::base() + delta, dumptime_oop_shift); 72 _mapped_heap_bottom = (intptr_t)mapped_heap_bottom; 73 _mapped_heap_delta = delta; 74 _mapped_heap_relocation_initialized = true; 75 } 76 77 void ArchiveHeapLoader::init_narrow_oop_decoding(address base, int shift) { 78 assert(!_narrow_oop_base_initialized, "only once"); 79 _narrow_oop_base_initialized = true; 80 _narrow_oop_base = base; 81 _narrow_oop_shift = shift; 82 } 83 84 void ArchiveHeapLoader::fixup_region() { 85 FileMapInfo* mapinfo = FileMapInfo::current_info(); 86 if (is_mapped()) { 87 mapinfo->fixup_mapped_heap_region(); 88 } else if (_loading_failed) { 89 fill_failed_loaded_heap(); 90 } 91 if (is_in_use()) { 92 if (!CDSConfig::is_using_full_module_graph()) { 93 // Need to remove all the archived java.lang.Module objects from HeapShared::roots(). 94 ClassLoaderDataShared::clear_archived_oops(); 95 } 96 } 97 } 98 99 // ------------------ Support for Region MAPPING ----------------------------------------- 100 101 // Patch all the embedded oop pointers inside an archived heap region, 102 // to be consistent with the runtime oop encoding. 103 class PatchCompressedEmbeddedPointers: public BitMapClosure { 104 narrowOop* _start; 105 106 public: 107 PatchCompressedEmbeddedPointers(narrowOop* start) : _start(start) {} 108 109 bool do_bit(size_t offset) { 110 narrowOop* p = _start + offset; 111 narrowOop v = *p; 112 assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time"); 113 oop o = ArchiveHeapLoader::decode_from_mapped_archive(v); 114 RawAccess<IS_NOT_NULL>::oop_store(p, o); 115 return true; 116 } 117 }; 118 119 class PatchCompressedEmbeddedPointersQuick: public BitMapClosure { 120 narrowOop* _start; 121 uint32_t _delta; 122 123 public: 124 PatchCompressedEmbeddedPointersQuick(narrowOop* start, uint32_t delta) : _start(start), _delta(delta) {} 125 126 bool do_bit(size_t offset) { 127 narrowOop* p = _start + offset; 128 narrowOop v = *p; 129 assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time"); 130 narrowOop new_v = CompressedOops::narrow_oop_cast(CompressedOops::narrow_oop_value(v) + _delta); 131 assert(!CompressedOops::is_null(new_v), "should never relocate to narrowOop(0)"); 132 #ifdef ASSERT 133 oop o1 = ArchiveHeapLoader::decode_from_mapped_archive(v); 134 oop o2 = CompressedOops::decode_not_null(new_v); 135 assert(o1 == o2, "quick delta must work"); 136 #endif 137 RawAccess<IS_NOT_NULL>::oop_store(p, new_v); 138 return true; 139 } 140 }; 141 142 class PatchUncompressedEmbeddedPointers: public BitMapClosure { 143 oop* _start; 144 intptr_t _delta; 145 146 public: 147 PatchUncompressedEmbeddedPointers(oop* start, intx runtime_offset) : 148 _start(start), 149 _delta(runtime_offset) {} 150 151 PatchUncompressedEmbeddedPointers(oop* start) : 152 _start(start), 153 _delta(ArchiveHeapLoader::mapped_heap_delta()) {} 154 155 bool do_bit(size_t offset) { 156 oop* p = _start + offset; 157 intptr_t dumptime_oop = (intptr_t)((void*)*p); 158 assert(dumptime_oop != 0, "null oops should have been filtered out at dump time"); 159 intptr_t runtime_oop = dumptime_oop + _delta; 160 RawAccess<IS_NOT_NULL>::oop_store(p, cast_to_oop(runtime_oop)); 161 return true; 162 } 163 }; 164 165 void ArchiveHeapLoader::patch_compressed_embedded_pointers(BitMapView bm, 166 FileMapInfo* info, 167 MemRegion region) { 168 narrowOop dt_encoded_bottom = info->encoded_heap_region_dumptime_address(); 169 narrowOop rt_encoded_bottom = CompressedOops::encode_not_null(cast_to_oop(region.start())); 170 log_info(cds)("patching heap embedded pointers: narrowOop 0x%8x -> 0x%8x", 171 (uint)dt_encoded_bottom, (uint)rt_encoded_bottom); 172 173 // Optimization: if dumptime shift is the same as runtime shift, we can perform a 174 // quick conversion from "dumptime narrowOop" -> "runtime narrowOop". 175 narrowOop* patching_start = (narrowOop*)region.start() + FileMapInfo::current_info()->heap_oopmap_start_pos(); 176 if (_narrow_oop_shift == CompressedOops::shift()) { 177 uint32_t quick_delta = (uint32_t)rt_encoded_bottom - (uint32_t)dt_encoded_bottom; 178 log_info(cds)("CDS heap data relocation quick delta = 0x%x", quick_delta); 179 if (quick_delta == 0) { 180 log_info(cds)("CDS heap data relocation unnecessary, quick_delta = 0"); 181 } else { 182 PatchCompressedEmbeddedPointersQuick patcher(patching_start, quick_delta); 183 bm.iterate(&patcher); 184 } 185 } else { 186 log_info(cds)("CDS heap data quick relocation not possible"); 187 PatchCompressedEmbeddedPointers patcher(patching_start); 188 bm.iterate(&patcher); 189 } 190 } 191 192 // Patch all the non-null pointers that are embedded in the archived heap objects 193 // in this (mapped) region 194 void ArchiveHeapLoader::patch_embedded_pointers(FileMapInfo* info, 195 MemRegion region, address oopmap, 196 size_t oopmap_size_in_bits) { 197 BitMapView bm((BitMap::bm_word_t*)oopmap, oopmap_size_in_bits); 198 if (UseCompressedOops) { 199 patch_compressed_embedded_pointers(bm, info, region); 200 } else { 201 PatchUncompressedEmbeddedPointers patcher((oop*)region.start() + FileMapInfo::current_info()->heap_oopmap_start_pos()); 202 bm.iterate(&patcher); 203 } 204 } 205 206 // ------------------ Support for Region LOADING ----------------------------------------- 207 208 // The CDS archive remembers each heap object by its address at dump time, but 209 // the heap object may be loaded at a different address at run time. This structure is used 210 // to translate the dump time addresses for all objects in FileMapInfo::space_at(region_index) 211 // to their runtime addresses. 212 struct LoadedArchiveHeapRegion { 213 int _region_index; // index for FileMapInfo::space_at(index) 214 size_t _region_size; // number of bytes in this region 215 uintptr_t _dumptime_base; // The dump-time (decoded) address of the first object in this region 216 intx _runtime_offset; // If an object's dump time address P is within in this region, its 217 // runtime address is P + _runtime_offset 218 uintptr_t top() { 219 return _dumptime_base + _region_size; 220 } 221 }; 222 223 void ArchiveHeapLoader::init_loaded_heap_relocation(LoadedArchiveHeapRegion* loaded_region) { 224 _dumptime_base = loaded_region->_dumptime_base; 225 _dumptime_top = loaded_region->top(); 226 _runtime_offset = loaded_region->_runtime_offset; 227 } 228 229 bool ArchiveHeapLoader::can_load() { 230 return Universe::heap()->can_load_archived_objects(); 231 } 232 233 class ArchiveHeapLoader::PatchLoadedRegionPointers: public BitMapClosure { 234 narrowOop* _start; 235 intx _offset; 236 uintptr_t _base; 237 uintptr_t _top; 238 239 public: 240 PatchLoadedRegionPointers(narrowOop* start, LoadedArchiveHeapRegion* loaded_region) 241 : _start(start), 242 _offset(loaded_region->_runtime_offset), 243 _base(loaded_region->_dumptime_base), 244 _top(loaded_region->top()) {} 245 246 bool do_bit(size_t offset) { 247 assert(UseCompressedOops, "PatchLoadedRegionPointers for uncompressed oops is unimplemented"); 248 narrowOop* p = _start + offset; 249 narrowOop v = *p; 250 assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time"); 251 uintptr_t o = cast_from_oop<uintptr_t>(ArchiveHeapLoader::decode_from_archive(v)); 252 assert(_base <= o && o < _top, "must be"); 253 254 o += _offset; 255 ArchiveHeapLoader::assert_in_loaded_heap(o); 256 RawAccess<IS_NOT_NULL>::oop_store(p, cast_to_oop(o)); 257 return true; 258 } 259 }; 260 261 bool ArchiveHeapLoader::init_loaded_region(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_region, 262 MemRegion& archive_space) { 263 size_t total_bytes = 0; 264 FileMapRegion* r = mapinfo->region_at(MetaspaceShared::hp); 265 r->assert_is_heap_region(); 266 if (r->used() == 0) { 267 return false; 268 } 269 270 assert(is_aligned(r->used(), HeapWordSize), "must be"); 271 total_bytes += r->used(); 272 loaded_region->_region_index = MetaspaceShared::hp; 273 loaded_region->_region_size = r->used(); 274 loaded_region->_dumptime_base = (uintptr_t)mapinfo->heap_region_dumptime_address(); 275 276 assert(is_aligned(total_bytes, HeapWordSize), "must be"); 277 size_t word_size = total_bytes / HeapWordSize; 278 HeapWord* buffer = Universe::heap()->allocate_loaded_archive_space(word_size); 279 if (buffer == nullptr) { 280 return false; 281 } 282 283 archive_space = MemRegion(buffer, word_size); 284 _loaded_heap_bottom = (uintptr_t)archive_space.start(); 285 _loaded_heap_top = _loaded_heap_bottom + total_bytes; 286 287 loaded_region->_runtime_offset = _loaded_heap_bottom - loaded_region->_dumptime_base; 288 289 return true; 290 } 291 292 bool ArchiveHeapLoader::load_heap_region_impl(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_region, 293 uintptr_t load_address) { 294 uintptr_t bitmap_base = (uintptr_t)mapinfo->map_bitmap_region(); 295 if (bitmap_base == 0) { 296 _loading_failed = true; 297 return false; // OOM or CRC error 298 } 299 300 FileMapRegion* r = mapinfo->region_at(loaded_region->_region_index); 301 if (!mapinfo->read_region(loaded_region->_region_index, (char*)load_address, r->used(), /* do_commit = */ false)) { 302 // There's no easy way to free the buffer, so we will fill it with zero later 303 // in fill_failed_loaded_heap(), and it will eventually be GC'ed. 304 log_warning(cds)("Loading of heap region %d has failed. Archived objects are disabled", loaded_region->_region_index); 305 _loading_failed = true; 306 return false; 307 } 308 assert(r->mapped_base() == (char*)load_address, "sanity"); 309 log_info(cds)("Loaded heap region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT 310 " size %6zu delta %zd", 311 loaded_region->_region_index, load_address, load_address + loaded_region->_region_size, 312 loaded_region->_region_size, loaded_region->_runtime_offset); 313 314 uintptr_t oopmap = bitmap_base + r->oopmap_offset(); 315 BitMapView bm((BitMap::bm_word_t*)oopmap, r->oopmap_size_in_bits()); 316 317 if (UseCompressedOops) { 318 PatchLoadedRegionPointers patcher((narrowOop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region); 319 bm.iterate(&patcher); 320 } else { 321 PatchUncompressedEmbeddedPointers patcher((oop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region->_runtime_offset); 322 bm.iterate(&patcher); 323 } 324 return true; 325 } 326 327 bool ArchiveHeapLoader::load_heap_region(FileMapInfo* mapinfo) { 328 assert(can_load(), "loaded heap for must be supported"); 329 init_narrow_oop_decoding(mapinfo->narrow_oop_base(), mapinfo->narrow_oop_shift()); 330 331 LoadedArchiveHeapRegion loaded_region; 332 memset(&loaded_region, 0, sizeof(loaded_region)); 333 334 MemRegion archive_space; 335 if (!init_loaded_region(mapinfo, &loaded_region, archive_space)) { 336 return false; 337 } 338 339 if (!load_heap_region_impl(mapinfo, &loaded_region, (uintptr_t)archive_space.start())) { 340 assert(_loading_failed, "must be"); 341 return false; 342 } 343 344 init_loaded_heap_relocation(&loaded_region); 345 _is_loaded = true; 346 347 return true; 348 } 349 350 class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure { 351 ResourceHashtable<uintptr_t, bool>* _table; 352 353 public: 354 VerifyLoadedHeapEmbeddedPointers(ResourceHashtable<uintptr_t, bool>* table) : _table(table) {} 355 356 virtual void do_oop(narrowOop* p) { 357 // This should be called before the loaded region is modified, so all the embedded pointers 358 // must be null, or must point to a valid object in the loaded region. 359 narrowOop v = *p; 360 if (!CompressedOops::is_null(v)) { 361 oop o = CompressedOops::decode_not_null(v); 362 uintptr_t u = cast_from_oop<uintptr_t>(o); 363 ArchiveHeapLoader::assert_in_loaded_heap(u); 364 guarantee(_table->contains(u), "must point to beginning of object in loaded archived region"); 365 } 366 } 367 virtual void do_oop(oop* p) { 368 oop v = *p; 369 if(v != nullptr) { 370 uintptr_t u = cast_from_oop<uintptr_t>(v); 371 ArchiveHeapLoader::assert_in_loaded_heap(u); 372 guarantee(_table->contains(u), "must point to beginning of object in loaded archived region"); 373 } 374 } 375 }; 376 377 void ArchiveHeapLoader::finish_initialization() { 378 if (is_loaded()) { 379 // These operations are needed only when the heap is loaded (not mapped). 380 finish_loaded_heap(); 381 if (VerifyArchivedFields > 0) { 382 verify_loaded_heap(); 383 } 384 } 385 if (is_in_use()) { 386 patch_native_pointers(); 387 intptr_t bottom = is_loaded() ? _loaded_heap_bottom : _mapped_heap_bottom; 388 389 // The heap roots are stored in one or more segments that are laid out consecutively. 390 // The size of each segment (except for the last one) is max_size_in_{elems,bytes}. 391 HeapRootSegments segments = FileMapInfo::current_info()->heap_root_segments(); 392 HeapShared::init_root_segment_sizes(segments.max_size_in_elems()); 393 intptr_t first_segment_addr = bottom + segments.base_offset(); 394 for (size_t c = 0; c < segments.count(); c++) { 395 oop segment_oop = cast_to_oop(first_segment_addr + (c * segments.max_size_in_bytes())); 396 assert(segment_oop->is_objArray(), "Must be"); 397 HeapShared::add_root_segment((objArrayOop)segment_oop); 398 } 399 } 400 } 401 402 void ArchiveHeapLoader::finish_loaded_heap() { 403 HeapWord* bottom = (HeapWord*)_loaded_heap_bottom; 404 HeapWord* top = (HeapWord*)_loaded_heap_top; 405 406 MemRegion archive_space = MemRegion(bottom, top); 407 Universe::heap()->complete_loaded_archive_space(archive_space); 408 } 409 410 void ArchiveHeapLoader::verify_loaded_heap() { 411 log_info(cds, heap)("Verify all oops and pointers in loaded heap"); 412 413 ResourceMark rm; 414 ResourceHashtable<uintptr_t, bool> table; 415 VerifyLoadedHeapEmbeddedPointers verifier(&table); 416 HeapWord* bottom = (HeapWord*)_loaded_heap_bottom; 417 HeapWord* top = (HeapWord*)_loaded_heap_top; 418 419 for (HeapWord* p = bottom; p < top; ) { 420 oop o = cast_to_oop(p); 421 table.put(cast_from_oop<uintptr_t>(o), true); 422 p += o->size(); 423 } 424 425 for (HeapWord* p = bottom; p < top; ) { 426 oop o = cast_to_oop(p); 427 o->oop_iterate(&verifier); 428 p += o->size(); 429 } 430 } 431 432 void ArchiveHeapLoader::fill_failed_loaded_heap() { 433 assert(_loading_failed, "must be"); 434 if (_loaded_heap_bottom != 0) { 435 assert(_loaded_heap_top != 0, "must be"); 436 HeapWord* bottom = (HeapWord*)_loaded_heap_bottom; 437 HeapWord* top = (HeapWord*)_loaded_heap_top; 438 Universe::heap()->fill_with_objects(bottom, top - bottom); 439 } 440 } 441 442 class PatchNativePointers: public BitMapClosure { 443 Metadata** _start; 444 445 public: 446 PatchNativePointers(Metadata** start) : _start(start) {} 447 448 bool do_bit(size_t offset) { 449 Metadata** p = _start + offset; 450 *p = (Metadata*)(address(*p) + MetaspaceShared::relocation_delta()); 451 return true; 452 } 453 }; 454 455 void ArchiveHeapLoader::patch_native_pointers() { 456 if (MetaspaceShared::relocation_delta() == 0) { 457 return; 458 } 459 460 FileMapRegion* r = FileMapInfo::current_info()->region_at(MetaspaceShared::hp); 461 if (r->mapped_base() != nullptr && r->has_ptrmap()) { 462 log_info(cds, heap)("Patching native pointers in heap region"); 463 BitMapView bm = FileMapInfo::current_info()->ptrmap_view(MetaspaceShared::hp); 464 PatchNativePointers patcher((Metadata**)r->mapped_base() + FileMapInfo::current_info()->heap_ptrmap_start_pos()); 465 bm.iterate(&patcher); 466 } 467 } 468 #endif // INCLUDE_CDS_JAVA_HEAP