1 /*
   2  * Copyright (c) 2025, 2026, 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/aotMapLogger.hpp"
  26 #include "cds/aotMappedHeapLoader.hpp"
  27 #include "cds/aotMappedHeapWriter.hpp"
  28 #include "cds/aotStreamedHeapLoader.hpp"
  29 #include "cds/aotStreamedHeapWriter.hpp"
  30 #include "cds/cdsConfig.hpp"
  31 #include "cds/filemap.hpp"
  32 #include "classfile/moduleEntry.hpp"
  33 #include "classfile/packageEntry.hpp"
  34 #include "classfile/systemDictionaryShared.hpp"
  35 #include "classfile/vmClasses.hpp"
  36 #include "logging/log.hpp"
  37 #include "logging/logStream.hpp"
  38 #include "memory/metaspaceClosure.hpp"
  39 #include "memory/resourceArea.hpp"
  40 #include "oops/method.hpp"
  41 #include "oops/methodCounters.hpp"
  42 #include "oops/methodData.hpp"
  43 #include "oops/oop.inline.hpp"
  44 #include "oops/trainingData.hpp"
  45 #include "runtime/fieldDescriptor.inline.hpp"
  46 #include "runtime/globals_extension.hpp"
  47 #include "utilities/growableArray.hpp"
  48 
  49 bool AOTMapLogger::_is_logging_at_bootstrap;
  50 bool AOTMapLogger::_is_runtime_logging;
  51 intx AOTMapLogger::_buffer_to_requested_delta;
  52 intx AOTMapLogger::_requested_to_mapped_metadata_delta;
  53 GrowableArrayCHeap<AOTMapLogger::FakeOop, mtClass>* AOTMapLogger::_roots;
  54 
  55 class AOTMapLogger::RequestedMetadataAddr {
  56   address _raw_addr;
  57 
  58 public:
  59   RequestedMetadataAddr(address raw_addr) : _raw_addr(raw_addr) {}
  60 
  61   address raw_addr() const { return _raw_addr; }
  62 
  63   Klass* to_real_klass() const {
  64     if (_raw_addr == nullptr) {
  65       return nullptr;
  66     }
  67 
  68     if (_is_runtime_logging) {
  69       return (Klass*)(_raw_addr + _requested_to_mapped_metadata_delta);
  70     } else {
  71       ArchiveBuilder* builder = ArchiveBuilder::current();
  72       address buffered_addr = builder->requested_to_buffered(_raw_addr);
  73       address klass = builder->get_source_addr(buffered_addr);
  74       return (Klass*)klass;
  75     }
  76   }
  77 }; // AOTMapLogger::RequestedMetadataAddr
  78 
  79 void AOTMapLogger::ergo_initialize() {
  80   if (!CDSConfig::is_dumping_archive() && CDSConfig::is_using_archive() && log_is_enabled(Info, aot, map)) {
  81     _is_logging_at_bootstrap = true;
  82     if (FLAG_IS_DEFAULT(ArchiveRelocationMode)) {
  83       FLAG_SET_ERGO(ArchiveRelocationMode, 0);
  84     } else if (ArchiveRelocationMode != 0) {
  85       log_warning(aot, map)("Addresses in the AOT map may be incorrect for -XX:ArchiveRelocationMode=%d.", ArchiveRelocationMode);
  86     }
  87   }
  88 }
  89 
  90 void AOTMapLogger::dumptime_log(ArchiveBuilder* builder, FileMapInfo* mapinfo,
  91                                 AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeapInfo* streamed_heap_info,
  92                                 char* bitmap, size_t bitmap_size_in_bytes) {
  93   _is_runtime_logging = false;
  94   _buffer_to_requested_delta =  ArchiveBuilder::current()->buffer_to_requested_delta();
  95 
  96   log_file_header(mapinfo);
  97 
  98   DumpRegion* rw_region = &builder->_rw_region;
  99   DumpRegion* ro_region = &builder->_ro_region;
 100 
 101   dumptime_log_metaspace_region("rw region", rw_region, &builder->_rw_src_objs);
 102   dumptime_log_metaspace_region("ro region", ro_region, &builder->_ro_src_objs);
 103 
 104   address bitmap_end = address(bitmap + bitmap_size_in_bytes);
 105   log_region_range("bitmap", address(bitmap), bitmap_end, nullptr);
 106   log_as_hex((address)bitmap, bitmap_end, nullptr);
 107 
 108 #if INCLUDE_CDS_JAVA_HEAP
 109   if (mapped_heap_info != nullptr && mapped_heap_info->is_used()) {
 110     dumptime_log_mapped_heap_region(mapped_heap_info);
 111   }
 112   if (streamed_heap_info != nullptr && streamed_heap_info->is_used()) {
 113     dumptime_log_streamed_heap_region(streamed_heap_info);
 114   }
 115 #endif
 116 
 117   log_info(aot, map)("[End of AOT cache map]");
 118 }
 119 
 120 // This class is used to find the location and type of all the
 121 // archived metaspace objects.
 122 class AOTMapLogger::RuntimeGatherArchivedMetaspaceObjs : public UniqueMetaspaceClosure {
 123   GrowableArrayCHeap<ArchivedObjInfo, mtClass> _objs;
 124 
 125   static int compare_objs_by_addr(ArchivedObjInfo* a, ArchivedObjInfo* b) {
 126     intx diff = a->_src_addr - b->_src_addr;
 127     if (diff < 0) {
 128       return -1;
 129     } else if (diff == 0) {
 130       return 0;
 131     } else {
 132       return 1;
 133     }
 134   }
 135 
 136 public:
 137   GrowableArrayCHeap<ArchivedObjInfo, mtClass>* objs() { return &_objs; }
 138 
 139   virtual bool do_unique_ref(Ref* ref, bool read_only) {
 140     ArchivedObjInfo info;
 141     if (AOTMetaspace::in_aot_cache(ref->obj())) {
 142       info._src_addr = ref->obj();
 143       info._buffered_addr = ref->obj();
 144       info._requested_addr = ref->obj();
 145       info._bytes = ref->size() * BytesPerWord;
 146       info._type = ref->type();
 147       _objs.append(info);
 148     }
 149 
 150     return true; // keep iterating
 151   }
 152 
 153   void finish() {
 154     UniqueMetaspaceClosure::finish();
 155     _objs.sort(compare_objs_by_addr);
 156   }
 157 }; // AOTMapLogger::RuntimeGatherArchivedMetaspaceObjs
 158 
 159 void AOTMapLogger::runtime_log(FileMapInfo* static_mapinfo, FileMapInfo* dynamic_mapinfo) {
 160   _is_runtime_logging = true;
 161   _requested_to_mapped_metadata_delta = static_mapinfo->relocation_delta();
 162 
 163   ResourceMark rm;
 164   RuntimeGatherArchivedMetaspaceObjs gatherer;
 165 
 166   if (log_is_enabled(Debug, aot, map)) {
 167     // The metaspace objects in the AOT cache are stored as a stream of bytes. For space
 168     // saving, we don't store a complete index that tells us where one object ends and
 169     // another object starts. There's also no type information.
 170     //
 171     // However, we can rebuild our index by iterating over all the objects using
 172     // MetaspaceClosure, starting from the dictionary of Klasses in SystemDictionaryShared.
 173     GrowableArray<Klass*> klasses;
 174     SystemDictionaryShared::get_all_archived_classes(/*is_static*/true, &klasses);
 175     if (dynamic_mapinfo != nullptr) {
 176       SystemDictionaryShared::get_all_archived_classes(/*is_static*/false, &klasses);
 177     }
 178 
 179     for (int i = 0; i < klasses.length(); i++) {
 180       gatherer.push(klasses.adr_at(i));
 181     }
 182     gatherer.finish();
 183   }
 184 
 185   runtime_log(static_mapinfo, gatherer.objs());
 186   if (dynamic_mapinfo != nullptr) {
 187     runtime_log(dynamic_mapinfo, gatherer.objs());
 188   }
 189 }
 190 
 191 void AOTMapLogger::runtime_log(FileMapInfo* mapinfo, GrowableArrayCHeap<ArchivedObjInfo, mtClass>* objs) {
 192   log_file_header(mapinfo);
 193 
 194   runtime_log_metaspace_regions(mapinfo, objs);
 195 
 196 #if INCLUDE_CDS_JAVA_HEAP
 197   if (mapinfo->has_heap_region() && CDSConfig::is_loading_heap()) {
 198     runtime_log_heap_region(mapinfo);
 199   }
 200 #endif
 201 
 202   log_info(aot, map)("[End of map]");
 203 }
 204 
 205 void AOTMapLogger::dumptime_log_metaspace_region(const char* name, DumpRegion* region,
 206                                                  const ArchiveBuilder::SourceObjList* src_objs) {
 207   address region_base = address(region->base());
 208   address region_top  = address(region->top());
 209   log_region_range(name, region_base, region_top, region_base + _buffer_to_requested_delta);
 210   if (log_is_enabled(Debug, aot, map)) {
 211     GrowableArrayCHeap<ArchivedObjInfo, mtClass> objs;
 212     for (int i = 0; i < src_objs->objs()->length(); i++) {
 213       ArchiveBuilder::SourceObjInfo* src_info = src_objs->at(i);
 214       ArchivedObjInfo info;
 215       info._src_addr = src_info->source_addr();
 216       info._buffered_addr = src_info->buffered_addr();
 217       info._requested_addr = info._buffered_addr + _buffer_to_requested_delta;
 218       info._bytes = src_info->size_in_bytes();
 219       info._type = src_info->type();
 220       objs.append(info);
 221     }
 222 
 223     log_metaspace_objects_impl(address(region->base()), address(region->end()), &objs, 0, objs.length());
 224   }
 225 }
 226 
 227 void AOTMapLogger::runtime_log_metaspace_regions(FileMapInfo* mapinfo, GrowableArrayCHeap<ArchivedObjInfo, mtClass>* objs) {
 228   FileMapRegion* rw = mapinfo->region_at(AOTMetaspace::rw);
 229   FileMapRegion* ro = mapinfo->region_at(AOTMetaspace::ro);
 230 
 231   address rw_base = address(rw->mapped_base());
 232   address rw_end  = address(rw->mapped_end());
 233   address ro_base = address(ro->mapped_base());
 234   address ro_end  = address(ro->mapped_end());
 235 
 236   int first_rw_index = -1;
 237   int first_ro_index = -1;
 238   int last_ro_index = -1;
 239 
 240   if (log_is_enabled(Debug, aot, map)) {
 241     int i = 0;
 242     for (; i < objs->length(); i++) {
 243       address p = objs->at(i)._src_addr;
 244       if (p < rw_base) {
 245         // We are printing the dynamic archive but found an object in the static archive
 246         precond(!mapinfo->is_static());
 247         continue;
 248       }
 249       if (first_rw_index < 0) {
 250         first_rw_index = i;
 251         continue;
 252       }
 253       if (p < ro_base) {
 254         continue;
 255       }
 256       if (first_ro_index < 0) {
 257         first_ro_index = i;
 258         continue;
 259       }
 260       if (p < ro_end) {
 261         continue;
 262       } else {
 263         last_ro_index = i;
 264         break;
 265       }
 266     }
 267   }
 268 
 269   if (last_ro_index < 0) {
 270     last_ro_index = objs->length();
 271   }
 272 
 273   log_region_range("rw", rw_base, rw_end, rw_base - _requested_to_mapped_metadata_delta);
 274   if (log_is_enabled(Debug, aot, map)) {
 275     log_metaspace_objects_impl(rw_base, rw_end, objs, first_rw_index, first_ro_index);
 276   }
 277 
 278   log_region_range("ro", ro_base, ro_end, ro_base - _requested_to_mapped_metadata_delta);
 279   if (log_is_enabled(Debug, aot, map)) {
 280     log_metaspace_objects_impl(ro_base, ro_end, objs, first_ro_index, last_ro_index);
 281   }
 282 }
 283 
 284 void AOTMapLogger::log_file_header(FileMapInfo* mapinfo) {
 285   const char* type;
 286   if (mapinfo->is_static()) {
 287     if (CDSConfig::new_aot_flags_used()) {
 288       type = "AOT cache";
 289     } else {
 290       type = "Static CDS archive";
 291     }
 292   } else {
 293     type = "Dynamic CDS archive";
 294   }
 295 
 296   log_info(aot, map)("%s map for %s", type, mapinfo->full_path());
 297 
 298   address header = address(mapinfo->header());
 299   address header_end = header + mapinfo->header()->header_size();
 300 
 301   log_region_range("header", header, header_end, nullptr);
 302   LogStreamHandle(Info, aot, map) lsh;
 303   mapinfo->print(&lsh);
 304   log_as_hex(header, header_end, nullptr);
 305 }
 306 
 307 // Log information about a region, whose address at dump time is [base .. top). At
 308 // runtime, this region will be mapped to requested_base. requested_base is nullptr if this
 309 // region will be mapped at os-selected addresses (such as the bitmap region), or will
 310 // be accessed with os::read (the header).
 311 void AOTMapLogger::log_region_range(const char* name, address base, address top, address requested_base) {
 312   size_t size = top - base;
 313   base = requested_base;
 314   if (requested_base == nullptr) {
 315     top = (address)size;
 316   } else {
 317     top = requested_base + size;
 318   }
 319   log_info(aot, map)("[%-18s " PTR_FORMAT " - " PTR_FORMAT " %9zu bytes]",
 320                      name, p2i(base), p2i(top), size);
 321 }
 322 
 323 #define _LOG_PREFIX PTR_FORMAT ": @@ %-17s %d"
 324 
 325 void AOTMapLogger::log_metaspace_objects_impl(address region_base, address region_end, GrowableArrayCHeap<ArchivedObjInfo, mtClass>* objs,
 326                                               int start_idx, int end_idx) {
 327   address last_obj_base = region_base;
 328   address last_obj_end  = region_base;
 329   Thread* current = Thread::current();
 330 
 331   for (int i = start_idx; i < end_idx; i++) {
 332     ArchivedObjInfo& info = objs->at(i);
 333     address src = info._src_addr;
 334     address buffered_addr = info._buffered_addr;
 335     address requested_addr = info._requested_addr;
 336     int bytes = info._bytes;
 337     MetaspaceClosureType type = info._type;
 338     const char* type_name = MetaspaceClosure::type_name(type);
 339 
 340     log_as_hex(last_obj_base, buffered_addr, last_obj_base + _buffer_to_requested_delta);
 341 
 342     switch (type) {
 343     case MetaspaceClosureType::ClassType:
 344       log_klass((Klass*)src, requested_addr, type_name, bytes, current);
 345       break;
 346     case MetaspaceClosureType::ConstantPoolType:
 347       log_constant_pool((ConstantPool*)src, requested_addr, type_name, bytes, current);
 348       break;
 349     case MetaspaceClosureType::ConstantPoolCacheType:
 350       log_constant_pool_cache((ConstantPoolCache*)src, requested_addr, type_name, bytes, current);
 351       break;
 352     case MetaspaceClosureType::ConstMethodType:
 353       log_const_method((ConstMethod*)src, requested_addr, type_name, bytes, current);
 354       break;
 355     case MetaspaceClosureType::MethodType:
 356       log_method((Method*)src, requested_addr, type_name, bytes, current);
 357       break;
 358     case MetaspaceClosureType::MethodCountersType:
 359       log_method_counters((MethodCounters*)src, requested_addr, type_name, bytes, current);
 360       break;
 361     case MetaspaceClosureType::MethodDataType:
 362       log_method_data((MethodData*)src, requested_addr, type_name, bytes, current);
 363       break;
 364     case MetaspaceClosureType::ModuleEntryType:
 365       log_module_entry((ModuleEntry*)src, requested_addr, type_name, bytes, current);
 366       break;
 367     case MetaspaceClosureType::PackageEntryType:
 368       log_package_entry((PackageEntry*)src, requested_addr, type_name, bytes, current);
 369       break;
 370     case MetaspaceClosureType::GrowableArrayType:
 371       log_growable_array((GrowableArrayBase*)src, requested_addr, type_name, bytes, current);
 372       break;
 373     case MetaspaceClosureType::SymbolType:
 374       log_symbol((Symbol*)src, requested_addr, type_name, bytes, current);
 375       break;
 376     case MetaspaceClosureType::KlassTrainingDataType:
 377       log_klass_training_data((KlassTrainingData*)src, requested_addr, type_name, bytes, current);
 378       break;
 379     case MetaspaceClosureType::MethodTrainingDataType:
 380       log_method_training_data((MethodTrainingData*)src, requested_addr, type_name, bytes, current);
 381       break;
 382     case MetaspaceClosureType::CompileTrainingDataType:
 383       log_compile_training_data((CompileTrainingData*)src, requested_addr, type_name, bytes, current);
 384       break;
 385     default:
 386       log_debug(aot, map)(_LOG_PREFIX, p2i(requested_addr), type_name, bytes);
 387       break;
 388     }
 389 
 390     last_obj_base = buffered_addr;
 391     last_obj_end  = buffered_addr + bytes;
 392   }
 393 
 394   log_as_hex(last_obj_base, last_obj_end, last_obj_base + _buffer_to_requested_delta);
 395   if (last_obj_end < region_end) {
 396     log_debug(aot, map)(PTR_FORMAT ": @@ Misc data %zu bytes",
 397                         p2i(last_obj_end + _buffer_to_requested_delta),
 398                         size_t(region_end - last_obj_end));
 399     log_as_hex(last_obj_end, region_end, last_obj_end + _buffer_to_requested_delta);
 400   }
 401 }
 402 
 403 void AOTMapLogger::log_constant_pool(ConstantPool* cp, address requested_addr,
 404                                      const char* type_name, int bytes, Thread* current) {
 405   ResourceMark rm(current);
 406   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,
 407                       cp->pool_holder()->external_name());
 408 }
 409 
 410 void AOTMapLogger::log_constant_pool_cache(ConstantPoolCache* cpc, address requested_addr,
 411                                            const char* type_name, int bytes, Thread* current) {
 412   ResourceMark rm(current);
 413   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,
 414                       cpc->constant_pool()->pool_holder()->external_name());
 415 }
 416 
 417 void AOTMapLogger::log_const_method(ConstMethod* cm, address requested_addr, const char* type_name,
 418                                     int bytes, Thread* current) {
 419   ResourceMark rm(current);
 420   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,  cm->method()->external_name());
 421 }
 422 
 423 void AOTMapLogger::log_method_counters(MethodCounters* mc, address requested_addr, const char* type_name,
 424                                       int bytes, Thread* current) {
 425   ResourceMark rm(current);
 426   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,  mc->method()->external_name());
 427 }
 428 
 429 void AOTMapLogger::log_method_data(MethodData* md, address requested_addr, const char* type_name,
 430                                    int bytes, Thread* current) {
 431   ResourceMark rm(current);
 432   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,  md->method()->external_name());
 433 }
 434 
 435 void AOTMapLogger::log_module_entry(ModuleEntry* mod, address requested_addr, const char* type_name,
 436                                    int bytes, Thread* current) {
 437   ResourceMark rm(current);
 438   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,
 439                       mod->name_as_C_string());
 440 }
 441 
 442 void AOTMapLogger::log_package_entry(PackageEntry* pkg, address requested_addr, const char* type_name,
 443                                    int bytes, Thread* current) {
 444   ResourceMark rm(current);
 445   log_debug(aot, map)(_LOG_PREFIX " %s - %s", p2i(requested_addr), type_name, bytes,
 446                       pkg->module()->name_as_C_string(), pkg->name_as_C_string());
 447 }
 448 
 449 void AOTMapLogger::log_growable_array(GrowableArrayBase* arr, address requested_addr, const char* type_name,
 450                                       int bytes, Thread* current) {
 451   ResourceMark rm(current);
 452   log_debug(aot, map)(_LOG_PREFIX " %d (%d)", p2i(requested_addr), type_name, bytes,
 453                       arr->length(), arr->capacity());
 454 }
 455 
 456 void AOTMapLogger::log_klass(Klass* k, address requested_addr, const char* type_name,
 457                              int bytes, Thread* current) {
 458   ResourceMark rm(current);
 459   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes, k->external_name());
 460 }
 461 
 462 void AOTMapLogger::log_method(Method* m, address requested_addr, const char* type_name,
 463                               int bytes, Thread* current) {
 464   ResourceMark rm(current);
 465   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,  m->external_name());
 466 }
 467 
 468 void AOTMapLogger::log_symbol(Symbol* s, address requested_addr, const char* type_name,
 469                               int bytes, Thread* current) {
 470   ResourceMark rm(current);
 471   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,
 472                       s->as_quoted_ascii());
 473 }
 474 
 475 void AOTMapLogger::log_klass_training_data(KlassTrainingData* ktd, address requested_addr, const char* type_name,
 476                                            int bytes, Thread* current) {
 477   ResourceMark rm(current);
 478   if (ktd->has_holder()) {
 479     log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,
 480                         ktd->name()->as_klass_external_name());
 481   } else {
 482     log_debug(aot, map)(_LOG_PREFIX, p2i(requested_addr), type_name, bytes);
 483   }
 484 }
 485 
 486 void AOTMapLogger::log_method_training_data(MethodTrainingData* mtd, address requested_addr, const char* type_name,
 487                                             int bytes, Thread* current) {
 488   ResourceMark rm(current);
 489   if (mtd->has_holder()) {
 490     log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,
 491                         mtd->holder()->external_name());
 492   } else {
 493     log_debug(aot, map)(_LOG_PREFIX, p2i(requested_addr), type_name, bytes);
 494   }
 495 }
 496 
 497 void AOTMapLogger::log_compile_training_data(CompileTrainingData* ctd, address requested_addr, const char* type_name,
 498                                              int bytes, Thread* current) {
 499   ResourceMark rm(current);
 500   if (ctd->method() != nullptr && ctd->method()->has_holder()) {
 501     log_debug(aot, map)(_LOG_PREFIX " %d %s", p2i(requested_addr), type_name, bytes,
 502                          ctd->level(), ctd->method()->holder()->external_name());
 503   } else {
 504     log_debug(aot, map)(_LOG_PREFIX, p2i(requested_addr), type_name, bytes);
 505   }
 506 }
 507 #undef _LOG_PREFIX
 508 
 509 // Log all the data [base...top). Pretend that the base address
 510 // will be mapped to requested_base at run-time.
 511 void AOTMapLogger::log_as_hex(address base, address top, address requested_base, bool is_heap) {
 512   assert(top >= base, "must be");
 513 
 514   LogStreamHandle(Trace, aot, map) lsh;
 515   if (lsh.is_enabled()) {
 516     int unitsize = sizeof(address);
 517     if (is_heap && UseCompressedOops) {
 518       // This makes the compressed oop pointers easier to read, but
 519       // longs and doubles will be split into two words.
 520       unitsize = sizeof(narrowOop);
 521     }
 522     os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
 523   }
 524 }
 525 
 526 #if INCLUDE_CDS_JAVA_HEAP
 527 // FakeOop (and subclasses FakeMirror, FakeString, FakeObjArray, FakeTypeArray) are used to traverse
 528 // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops:
 529 // - They do not reside inside the range of the heap.
 530 // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*)
 531 // - For -UseCompressedOops: pointers are not direct: see FakeOop::read_oop_at(oop*)
 532 //
 533 // Hence, in general, we cannot use regular oop API (such as oopDesc::obj_field()) on these objects. There
 534 // are a few rare case where regular oop API work, but these are all guarded with the raw_oop() method and
 535 // should be used with care.
 536 //
 537 // Each AOT heap reader and writer has its own oop_iterator() API that retrieves all the data required to build
 538 // fake oops for logging.
 539 class AOTMapLogger::FakeOop {
 540   OopDataIterator* _iter;
 541   OopData _data;
 542 
 543   address* buffered_field_addr(int field_offset) {
 544     return (address*)(buffered_addr() + field_offset);
 545   }
 546 
 547 public:
 548   RequestedMetadataAddr metadata_field(int field_offset) {
 549     return RequestedMetadataAddr(*(address*)(buffered_field_addr(field_offset)));
 550   }
 551 
 552   address buffered_addr() {
 553     return _data._buffered_addr;
 554   }
 555 
 556   // Return an "oop" pointer so we can use APIs that accept regular oops. This
 557   // must be used with care, as only a limited number of APIs can work with oops that
 558   // live outside of the range of the heap.
 559   oop raw_oop() { return _data._raw_oop; }
 560 
 561   FakeOop() : _data() {}
 562   FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {}
 563 
 564   FakeMirror as_mirror();
 565   FakeObjArray as_obj_array();
 566   FakeString as_string();
 567   FakeTypeArray as_type_array();
 568 
 569   RequestedMetadataAddr klass() {
 570     address rk = (address)real_klass();
 571     if (_is_runtime_logging) {
 572       return RequestedMetadataAddr(rk - _requested_to_mapped_metadata_delta);
 573     } else {
 574       ArchiveBuilder* builder = ArchiveBuilder::current();
 575       return builder->to_requested(builder->get_buffered_addr(rk));
 576     }
 577   }
 578 
 579   Klass* real_klass() {
 580     assert(UseCompressedClassPointers, "heap archiving requires UseCompressedClassPointers");
 581     return _data._klass;
 582   }
 583 
 584   // in heap words
 585   size_t size() {
 586     return _data._size;
 587   }
 588 
 589   bool is_root_segment() {
 590     return _data._is_root_segment;
 591   }
 592 
 593   bool is_array() { return real_klass()->is_array_klass(); }
 594   bool is_null() { return buffered_addr() == nullptr; }
 595 
 596   int array_length() {
 597     precond(is_array());
 598     return arrayOop(raw_oop())->length();
 599   }
 600 
 601   intptr_t target_location() {
 602     return _data._target_location;
 603   }
 604 
 605   address requested_addr() {
 606     return _data._requested_addr;
 607   }
 608 
 609   uint32_t as_narrow_oop_value() {
 610     precond(UseCompressedOops);
 611     return _data._narrow_location;
 612   }
 613 
 614   FakeOop read_oop_at(narrowOop* addr) { // +UseCompressedOops
 615     return FakeOop(_iter, _iter->obj_at(addr));
 616   }
 617 
 618   FakeOop read_oop_at(oop* addr) { // -UseCompressedOops
 619     return FakeOop(_iter, _iter->obj_at(addr));
 620   }
 621 
 622   FakeOop obj_field(int field_offset) {
 623     if (UseCompressedOops) {
 624       return read_oop_at(raw_oop()->field_addr<narrowOop>(field_offset));
 625     } else {
 626       return read_oop_at(raw_oop()->field_addr<oop>(field_offset));
 627     }
 628   }
 629 
 630   void print_non_oop_field(outputStream* st, fieldDescriptor* fd) {
 631     // fd->print_on_for() works for non-oop fields in fake oops
 632     precond(fd->field_type() != T_ARRAY && fd->field_type() != T_OBJECT);
 633     fd->print_on_for(st, raw_oop());
 634   }
 635 }; // AOTMapLogger::FakeOop
 636 
 637 class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop {
 638 public:
 639   FakeMirror(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 640 
 641   void print_class_signature_on(outputStream* st);
 642 
 643   Klass* real_mirrored_klass() {
 644     RequestedMetadataAddr mirrored_klass = metadata_field(java_lang_Class::klass_offset());
 645     return mirrored_klass.to_real_klass();
 646   }
 647 
 648   int static_oop_field_count() {
 649     return java_lang_Class::static_oop_field_count(raw_oop());
 650   }
 651 }; // AOTMapLogger::FakeMirror
 652 
 653 class AOTMapLogger::FakeObjArray : public AOTMapLogger::FakeOop {
 654   objArrayOop raw_objArrayOop() {
 655     return (objArrayOop)raw_oop();
 656   }
 657 
 658 public:
 659   FakeObjArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 660 
 661   int length() {
 662     return raw_objArrayOop()->length();
 663   }
 664   FakeOop obj_at(int i) {
 665     if (UseCompressedOops) {
 666       return read_oop_at(raw_objArrayOop()->obj_at_addr<narrowOop>(i));
 667     } else {
 668       return read_oop_at(raw_objArrayOop()->obj_at_addr<oop>(i));
 669     }
 670   }
 671 }; // AOTMapLogger::FakeObjArray
 672 
 673 class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop {
 674 public:
 675   FakeString(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 676 
 677   bool is_latin1() {
 678     jbyte coder = raw_oop()->byte_field(java_lang_String::coder_offset());
 679     assert(CompactStrings || coder == java_lang_String::CODER_UTF16, "Must be UTF16 without CompactStrings");
 680     return coder == java_lang_String::CODER_LATIN1;
 681   }
 682 
 683   FakeTypeArray value();
 684 
 685   int length();
 686   void print_on(outputStream* st, int max_length = MaxStringPrintSize);
 687 }; // AOTMapLogger::FakeString
 688 
 689 class AOTMapLogger::FakeTypeArray : public AOTMapLogger::FakeOop {
 690   typeArrayOop raw_typeArrayOop() {
 691     return (typeArrayOop)raw_oop();
 692   }
 693 
 694 public:
 695   FakeTypeArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 696 
 697   void print_elements_on(outputStream* st) {
 698     TypeArrayKlass::cast(real_klass())->oop_print_elements_on(raw_typeArrayOop(), st);
 699   }
 700 
 701   int length() { return raw_typeArrayOop()->length(); }
 702   jbyte byte_at(int i) { return raw_typeArrayOop()->byte_at(i); }
 703   jchar char_at(int i) { return raw_typeArrayOop()->char_at(i); }
 704 }; // AOTMapLogger::FakeTypeArray
 705 
 706 AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() {
 707   precond(real_klass() == vmClasses::Class_klass());
 708   return FakeMirror(_iter, _data);
 709 }
 710 
 711 AOTMapLogger::FakeObjArray AOTMapLogger::FakeOop::as_obj_array() {
 712   precond(real_klass()->is_objArray_klass());
 713   return FakeObjArray(_iter, _data);
 714 }
 715 
 716 AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() {
 717   precond(real_klass()->is_typeArray_klass());
 718   return FakeTypeArray(_iter, _data);
 719 }
 720 
 721 AOTMapLogger::FakeString AOTMapLogger::FakeOop::as_string() {
 722   precond(real_klass() == vmClasses::String_klass());
 723   return FakeString(_iter, _data);
 724 }
 725 
 726 void AOTMapLogger::FakeMirror::print_class_signature_on(outputStream* st) {
 727   ResourceMark rm;
 728   RequestedMetadataAddr requested_klass = metadata_field(java_lang_Class::klass_offset());
 729   Klass* real_klass = requested_klass.to_real_klass();
 730 
 731   if (real_klass == nullptr) {
 732     // This is a primitive mirror (Java expressions of int.class, long.class, void.class, etc);
 733     RequestedMetadataAddr requested_array_klass = metadata_field(java_lang_Class::array_klass_offset());
 734     Klass* real_array_klass = requested_array_klass.to_real_klass();
 735     if (real_array_klass == nullptr) {
 736       st->print(" V"); // The special mirror for void.class that doesn't have any representation in C++
 737     } else {
 738       precond(real_array_klass->is_typeArray_klass());
 739       st->print(" %c", real_array_klass->name()->char_at(1));
 740     }
 741   } else {
 742     const char* class_name = real_klass->name()->as_C_string();
 743     if (real_klass->is_instance_klass()) {
 744       st->print(" L%s;", class_name);
 745     } else {
 746       st->print(" %s", class_name);
 747     }
 748     if (real_klass->has_aot_initialized_mirror()) {
 749       st->print(" (aot-inited)");
 750     }
 751   }
 752 }
 753 
 754 AOTMapLogger::FakeTypeArray AOTMapLogger::FakeString::value() {
 755   return obj_field(java_lang_String::value_offset()).as_type_array();
 756 }
 757 
 758 int AOTMapLogger::FakeString::length() {
 759   FakeTypeArray v = value();
 760   if (v.is_null()) {
 761     return 0;
 762   }
 763   int arr_length = v.length();
 764   if (!is_latin1()) {
 765     assert((arr_length & 1) == 0, "should be even for UTF16 string");
 766     arr_length >>= 1; // convert number of bytes to number of elements
 767   }
 768   return arr_length;
 769 }
 770 
 771 void AOTMapLogger::FakeString::print_on(outputStream* st, int max_length) {
 772   FakeTypeArray v = value();
 773   int length = this->length();
 774   bool is_latin1 = this->is_latin1();
 775   bool abridge = length > max_length;
 776 
 777   st->print("\"");
 778   for (int index = 0; index < length; index++) {
 779     // If we need to abridge and we've printed half the allowed characters
 780     // then jump to the tail of the string.
 781     if (abridge && index >= max_length / 2) {
 782       st->print(" ... (%d characters ommitted) ... ", length - 2 * (max_length / 2));
 783       index = length - (max_length / 2);
 784       abridge = false; // only do this once
 785     }
 786     jchar c = (!is_latin1) ?  v.char_at(index) :
 787                              ((jchar) v.byte_at(index)) & 0xff;
 788     if (c < ' ') {
 789       st->print("\\x%02X", c); // print control characters e.g. \x0A
 790     } else {
 791       st->print("%c", c);
 792     }
 793   }
 794   st->print("\"");
 795 
 796   if (length > max_length) {
 797     st->print(" (abridged) ");
 798   }
 799 }
 800 
 801 class AOTMapLogger::ArchivedFieldPrinter : public FieldClosure {
 802   FakeOop _fake_oop;
 803   outputStream* _st;
 804 public:
 805   ArchivedFieldPrinter(FakeOop fake_oop, outputStream* st) : _fake_oop(fake_oop), _st(st) {}
 806 
 807   void do_field(fieldDescriptor* fd) {
 808     _st->print(" - ");
 809     BasicType ft = fd->field_type();
 810     switch (ft) {
 811     case T_ARRAY:
 812     case T_OBJECT:
 813       {
 814         fd->print_on(_st); // print just the name and offset
 815         FakeOop field_value = _fake_oop.obj_field(fd->offset());
 816         print_oop_info_cr(_st, field_value);
 817       }
 818       break;
 819     default:
 820       _fake_oop.print_non_oop_field(_st, fd); // name, offset, value
 821       _st->cr();
 822     }
 823   }
 824 }; // AOTMapLogger::ArchivedFieldPrinter
 825 
 826 void AOTMapLogger::dumptime_log_mapped_heap_region(AOTMappedHeapInfo* heap_info) {
 827   MemRegion r = heap_info->buffer_region();
 828   address buffer_start = address(r.start()); // start of the current oop inside the buffer
 829   address buffer_end = address(r.end());
 830 
 831   address requested_base = UseCompressedOops ? AOTMappedHeapWriter::narrow_oop_base() : (address)AOTMappedHeapWriter::NOCOOPS_REQUESTED_BASE;
 832   address requested_start = UseCompressedOops ? AOTMappedHeapWriter::buffered_addr_to_requested_addr(buffer_start) : requested_base;
 833 
 834   log_region_range("heap", buffer_start, buffer_end, requested_start);
 835   log_archived_objects(AOTMappedHeapWriter::oop_iterator(heap_info));
 836 }
 837 
 838 void AOTMapLogger::dumptime_log_streamed_heap_region(AOTStreamedHeapInfo* heap_info) {
 839   MemRegion r = heap_info->buffer_region();
 840   address buffer_start = address(r.start()); // start of the current oop inside the buffer
 841   address buffer_end = address(r.end());
 842 
 843   log_region_range("heap", buffer_start, buffer_end, nullptr);
 844   log_archived_objects(AOTStreamedHeapWriter::oop_iterator(heap_info));
 845 }
 846 
 847 void AOTMapLogger::runtime_log_heap_region(FileMapInfo* mapinfo) {
 848   ResourceMark rm;
 849 
 850   int heap_region_index = AOTMetaspace::hp;
 851   FileMapRegion* r = mapinfo->region_at(heap_region_index);
 852   size_t alignment = (size_t)ObjectAlignmentInBytes;
 853 
 854   if (mapinfo->object_streaming_mode()) {
 855     address buffer_start = (address)r->mapped_base();
 856     address buffer_end = buffer_start + r->used();
 857     log_region_range("heap", buffer_start, buffer_end, nullptr);
 858     log_archived_objects(AOTStreamedHeapLoader::oop_iterator(mapinfo, buffer_start, buffer_end));
 859   } else {
 860     // Allocate a buffer and read the image of the archived heap region. This buffer is outside
 861     // of the real Java heap, so we must use FakeOop to access the contents of the archived heap objects.
 862     char* buffer = resource_allocate_bytes(r->used() + alignment);
 863     address buffer_start = (address)align_up(buffer, alignment);
 864     address buffer_end = buffer_start + r->used();
 865     if (!mapinfo->read_region(heap_region_index, (char*)buffer_start, r->used(), /* do_commit = */ false)) {
 866       log_error(aot)("Cannot read heap region; AOT map logging of heap objects failed");
 867       return;
 868     }
 869 
 870     address requested_base = UseCompressedOops ? (address)mapinfo->narrow_oop_base() : AOTMappedHeapLoader::heap_region_requested_address(mapinfo);
 871     address requested_start = requested_base + r->mapping_offset();
 872     log_region_range("heap", buffer_start, buffer_end, requested_start);
 873     log_archived_objects(AOTMappedHeapLoader::oop_iterator(mapinfo, buffer_start, buffer_end));
 874   }
 875 }
 876 
 877 void AOTMapLogger::log_archived_objects(OopDataIterator* iter) {
 878   LogStreamHandle(Debug, aot, map) st;
 879   if (!st.is_enabled()) {
 880     return;
 881   }
 882 
 883   _roots = new GrowableArrayCHeap<FakeOop, mtClass>();
 884 
 885   // Roots that are not segmented
 886   GrowableArrayCHeap<OopData, mtClass>* normal_roots = iter->roots();
 887   for (int i = 0; i < normal_roots->length(); ++i) {
 888     OopData data = normal_roots->at(i);
 889     FakeOop fop(iter, data);
 890     _roots->append(fop);
 891     st.print(" root[%4d]: ", i);
 892     print_oop_info_cr(&st, fop);
 893   }
 894 
 895   while (iter->has_next()) {
 896     FakeOop fake_oop(iter, iter->next());
 897     st.print(PTR_FORMAT ": @@ Object ", fake_oop.target_location());
 898     print_oop_info_cr(&st, fake_oop, /*print_location=*/false);
 899 
 900     LogStreamHandle(Trace, aot, map, oops) trace_st;
 901     if (trace_st.is_enabled()) {
 902       print_oop_details(fake_oop, &trace_st);
 903     }
 904 
 905     address fop = fake_oop.buffered_addr();
 906     address end_fop = fop + fake_oop.size() * BytesPerWord;
 907     log_as_hex(fop, end_fop, fake_oop.requested_addr(), /*is_heap=*/true);
 908   }
 909 
 910   delete _roots;
 911   delete iter;
 912   delete normal_roots;
 913 }
 914 
 915 void AOTMapLogger::print_oop_info_cr(outputStream* st, FakeOop fake_oop, bool print_location) {
 916   if (fake_oop.is_null()) {
 917     st->print_cr("null");
 918   } else {
 919     ResourceMark rm;
 920     Klass* real_klass = fake_oop.real_klass();
 921     intptr_t target_location = fake_oop.target_location();
 922     if (print_location) {
 923       st->print(PTR_FORMAT " ", target_location);
 924     }
 925     if (UseCompressedOops) {
 926       st->print("(0x%08x) ", fake_oop.as_narrow_oop_value());
 927     }
 928     if (fake_oop.is_array()) {
 929       int array_len = fake_oop.array_length();
 930       st->print_cr("%s length: %d", real_klass->external_name(), array_len);
 931     } else {
 932       st->print("%s", real_klass->external_name());
 933 
 934       if (real_klass == vmClasses::String_klass()) {
 935         st->print(" ");
 936         FakeString fake_str = fake_oop.as_string();
 937         fake_str.print_on(st);
 938       } else if (real_klass == vmClasses::Class_klass()) {
 939         fake_oop.as_mirror().print_class_signature_on(st);
 940       }
 941 
 942       st->cr();
 943     }
 944   }
 945 }
 946 
 947 // Print the fields of instanceOops, or the elements of arrayOops
 948 void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) {
 949   Klass* real_klass = fake_oop.real_klass();
 950 
 951   st->print(" - klass: ");
 952   real_klass->print_value_on(st);
 953   st->print(" " PTR_FORMAT, p2i(fake_oop.klass().raw_addr()));
 954   st->cr();
 955 
 956   if (real_klass->is_typeArray_klass()) {
 957     fake_oop.as_type_array().print_elements_on(st);
 958   } else if (real_klass->is_objArray_klass()) {
 959     FakeObjArray fake_obj_array = fake_oop.as_obj_array();
 960     bool is_logging_root_segment = fake_oop.is_root_segment();
 961 
 962     for (int i = 0; i < fake_obj_array.length(); i++) {
 963       FakeOop elm = fake_obj_array.obj_at(i);
 964       if (is_logging_root_segment) {
 965         st->print(" root[%4d]: ", _roots->length());
 966         _roots->append(elm);
 967       } else {
 968         st->print(" -%4d: ", i);
 969       }
 970       print_oop_info_cr(st, elm);
 971     }
 972   } else {
 973     st->print_cr(" - fields (%zu words):", fake_oop.size());
 974 
 975     ArchivedFieldPrinter print_field(fake_oop, st);
 976     InstanceKlass::cast(real_klass)->print_nonstatic_fields(&print_field);
 977 
 978     if (real_klass == vmClasses::Class_klass()) {
 979       FakeMirror fake_mirror = fake_oop.as_mirror();
 980 
 981       st->print(" - signature: ");
 982       fake_mirror.print_class_signature_on(st);
 983       st->cr();
 984 
 985       Klass* real_mirrored_klass = fake_mirror.real_mirrored_klass();
 986       if (real_mirrored_klass != nullptr && real_mirrored_klass->is_instance_klass()) {
 987         InstanceKlass* real_mirrored_ik = InstanceKlass::cast(real_mirrored_klass);
 988 
 989         ConstantPoolCache* cp_cache = real_mirrored_ik->constants()->cache();
 990         if (!_is_runtime_logging) {
 991           cp_cache = ArchiveBuilder::current()->get_buffered_addr(cp_cache);
 992         }
 993         int rr_root_index = cp_cache->archived_references_index();
 994         st->print(" - resolved_references: ");
 995         if (rr_root_index >= 0) {
 996           FakeOop resolved_references = _roots->at(rr_root_index);
 997           print_oop_info_cr(st, resolved_references);
 998         } else {
 999           st->print("null");
1000         }
1001 
1002         st->print_cr("- ---- static fields (%d):", fake_mirror.static_oop_field_count());
1003         real_mirrored_ik->do_local_static_fields(&print_field);
1004       }
1005     }
1006   }
1007 }
1008 #endif // INCLUDE_CDS_JAVA_HEAP