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