< prev index next >

src/hotspot/share/cds/archiveBuilder.cpp

Print this page
*** 30,10 ***
--- 30,11 ---
  #include "cds/archiveUtils.hpp"
  #include "cds/cdsConfig.hpp"
  #include "cds/cppVtables.hpp"
  #include "cds/dumpAllocStats.hpp"
  #include "cds/dynamicArchive.hpp"
+ #include "cds/finalImageRecipes.hpp"
  #include "cds/heapShared.hpp"
  #include "cds/metaspaceShared.hpp"
  #include "cds/regeneratedClasses.hpp"
  #include "classfile/classLoader.hpp"
  #include "classfile/classLoaderDataShared.hpp"

*** 49,13 ***
--- 50,16 ---
  #include "memory/allStatic.hpp"
  #include "memory/memRegion.hpp"
  #include "memory/resourceArea.hpp"
  #include "oops/compressedKlass.inline.hpp"
  #include "oops/instanceKlass.hpp"
+ #include "oops/methodCounters.hpp"
+ #include "oops/methodData.hpp"
  #include "oops/objArrayKlass.hpp"
  #include "oops/objArrayOop.inline.hpp"
  #include "oops/oopHandle.inline.hpp"
+ #include "oops/trainingData.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/fieldDescriptor.inline.hpp"
  #include "runtime/globals_extension.hpp"
  #include "runtime/javaThread.hpp"
  #include "runtime/sharedRuntime.hpp"

*** 162,13 ***
--- 166,15 ---
    _mapped_static_archive_bottom(nullptr),
    _mapped_static_archive_top(nullptr),
    _buffer_to_requested_delta(0),
    _rw_region("rw", MAX_SHARED_DELTA),
    _ro_region("ro", MAX_SHARED_DELTA),
+   _cc_region("cc", MAX_SHARED_DELTA),
    _ptrmap(mtClassShared),
    _rw_ptrmap(mtClassShared),
    _ro_ptrmap(mtClassShared),
+   _cc_ptrmap(mtClassShared),
    _rw_src_objs(),
    _ro_src_objs(),
    _src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
    _buffered_to_src_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
    _total_heap_region_size(0),

*** 316,11 ***
  
  size_t ArchiveBuilder::estimate_archive_size() {
    // size of the symbol table and two dictionaries, plus the RunTimeClassInfo's
    size_t symbol_table_est = SymbolTable::estimate_size_for_archive();
    size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive();
!   _estimated_hashtable_bytes = symbol_table_est + dictionary_est;
  
    if (CDSConfig::is_dumping_aot_linked_classes()) {
      // This is difficult to estimate when dumping the dynamic archive, as the
      // AOTLinkedClassTable may need to contain classes in the static archive as well.
      //
--- 322,21 ---
  
  size_t ArchiveBuilder::estimate_archive_size() {
    // size of the symbol table and two dictionaries, plus the RunTimeClassInfo's
    size_t symbol_table_est = SymbolTable::estimate_size_for_archive();
    size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive();
!   size_t training_data_est = TrainingData::estimate_size_for_archive();
+   _estimated_hashtable_bytes = symbol_table_est + dictionary_est + training_data_est;
+ 
+   if (CDSConfig::is_dumping_final_static_archive()) {
+     _estimated_hashtable_bytes += 200 * 1024 * 1024; // FIXME -- need to iterate archived symbols??
+   }
+ 
+   if (CDSConfig::is_dumping_dynamic_archive()) {
+     // Some extra space for traning data. Be generous. Unused areas will be trimmed from the archive file.
+     _estimated_hashtable_bytes += 200 * 1024 * 1024;
+   }
  
    if (CDSConfig::is_dumping_aot_linked_classes()) {
      // This is difficult to estimate when dumping the dynamic archive, as the
      // AOTLinkedClassTable may need to contain classes in the static archive as well.
      //

*** 545,11 ***
    if (klass->is_instance_klass()) {
      InstanceKlass* ik = InstanceKlass::cast(klass);
      return SystemDictionaryShared::is_excluded_class(ik);
    } else if (klass->is_objArray_klass()) {
      Klass* bottom = ObjArrayKlass::cast(klass)->bottom_klass();
!     if (MetaspaceShared::is_shared_static(bottom)) {
        // The bottom class is in the static archive so it's clearly not excluded.
        assert(CDSConfig::is_dumping_dynamic_archive(), "sanity");
        return false;
      } else if (bottom->is_instance_klass()) {
        return SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(bottom));
--- 561,11 ---
    if (klass->is_instance_klass()) {
      InstanceKlass* ik = InstanceKlass::cast(klass);
      return SystemDictionaryShared::is_excluded_class(ik);
    } else if (klass->is_objArray_klass()) {
      Klass* bottom = ObjArrayKlass::cast(klass)->bottom_klass();
!     if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_shared_static(bottom)) {
        // The bottom class is in the static archive so it's clearly not excluded.
        assert(CDSConfig::is_dumping_dynamic_archive(), "sanity");
        return false;
      } else if (bottom->is_instance_klass()) {
        return SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(bottom));

*** 559,16 ***
    return false;
  }
  
  ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref *ref) {
    address obj = ref->obj();
!   if (MetaspaceShared::is_in_shared_metaspace(obj)) {
      // Don't dump existing shared metadata again.
      return point_to_it;
    } else if (ref->msotype() == MetaspaceObj::MethodDataType ||
!              ref->msotype() == MetaspaceObj::MethodCountersType) {
!     return set_to_null;
    } else {
      if (ref->msotype() == MetaspaceObj::ClassType) {
        Klass* klass = (Klass*)ref->obj();
        assert(klass->is_klass(), "must be");
        if (is_excluded(klass)) {
--- 575,19 ---
    return false;
  }
  
  ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref *ref) {
    address obj = ref->obj();
!   if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_in_shared_metaspace(obj)) {
      // Don't dump existing shared metadata again.
      return point_to_it;
    } else if (ref->msotype() == MetaspaceObj::MethodDataType ||
!              ref->msotype() == MetaspaceObj::MethodCountersType ||
!              ref->msotype() == MetaspaceObj::KlassTrainingDataType ||
+              ref->msotype() == MetaspaceObj::MethodTrainingDataType ||
+              ref->msotype() == MetaspaceObj::CompileTrainingDataType) {
+       return TrainingData::need_data() ? make_a_copy : set_to_null;
    } else {
      if (ref->msotype() == MetaspaceObj::ClassType) {
        Klass* klass = (Klass*)ref->obj();
        assert(klass->is_klass(), "must be");
        if (is_excluded(klass)) {

*** 776,10 ***
--- 795,15 ---
           p2i(src_addr));
  
    return p->buffered_addr();
  }
  
+ bool ArchiveBuilder::has_been_archived(address src_addr) const {
+   SourceObjInfo* p = _src_obj_table.get(src_addr);
+   return (p != nullptr);
+ }
+ 
  address ArchiveBuilder::get_source_addr(address buffered_addr) const {
    assert(is_in_buffer_space(buffered_addr), "must be");
    address* src_p = _buffered_to_src_table.get(buffered_addr);
    assert(src_p != nullptr && *src_p != nullptr, "must be");
    return *src_p;

*** 989,15 ***
--- 1013,39 ---
  #undef STATS_PARAMS
  
    DynamicArchive::make_array_klasses_shareable();
  }
  
+ void ArchiveBuilder::make_training_data_shareable() {
+   auto clean_td = [&] (address& src_obj,  SourceObjInfo& info) {
+     if (!is_in_buffer_space(info.buffered_addr())) {
+       return;
+     }
+ 
+     if (info.msotype() == MetaspaceObj::KlassTrainingDataType ||
+         info.msotype() == MetaspaceObj::MethodTrainingDataType ||
+         info.msotype() == MetaspaceObj::CompileTrainingDataType) {
+       TrainingData* buffered_td = (TrainingData*)info.buffered_addr();
+       buffered_td->remove_unshareable_info();
+     } else if (info.msotype() == MetaspaceObj::MethodDataType) {
+       MethodData* buffered_mdo = (MethodData*)info.buffered_addr();
+       buffered_mdo->remove_unshareable_info();
+     } else if (info.msotype() == MetaspaceObj::MethodCountersType) {
+       MethodCounters* buffered_mc = (MethodCounters*)info.buffered_addr();
+       buffered_mc->remove_unshareable_info();
+     }
+   };
+   _src_obj_table.iterate_all(clean_td);
+ }
+ 
  void ArchiveBuilder::serialize_dynamic_archivable_items(SerializeClosure* soc) {
    SymbolTable::serialize_shared_table_header(soc, false);
    SystemDictionaryShared::serialize_dictionary_headers(soc, false);
    DynamicArchive::serialize_array_klasses(soc);
    AOTLinkedClassBulkLoader::serialize(soc, false);
+   FinalImageRecipes::serialize(soc, false);
+   TrainingData::serialize_training_data(soc);
  }
  
  uintx ArchiveBuilder::buffer_to_offset(address p) const {
    address requested_p = to_requested(p);
    assert(requested_p >= _requested_static_archive_bottom, "must be");

*** 1014,10 ***
--- 1062,19 ---
      p = get_buffered_addr(p);
    }
    return buffer_to_offset(p);
  }
  
+ void ArchiveBuilder::start_cc_region() {
+   ro_region()->pack();
+   start_dump_region(&_cc_region);
+ }
+ 
+ void ArchiveBuilder::end_cc_region() {
+   _cc_region.pack();
+ }
+ 
  address ArchiveBuilder::offset_to_buffered_address(u4 offset) const {
    address requested_addr = _requested_static_archive_bottom + offset;
    address buffered_addr = requested_addr - _buffer_to_requested_delta;
    assert(is_in_buffer_space(buffered_addr), "bad offset");
    return buffered_addr;

*** 1130,11 ***
    return UseCompactObjectHeaders ?  CompressedKlassPointers::max_shift() : 0;
  }
  #endif // _LP64
  
  void ArchiveBuilder::relocate_to_requested() {
!   ro_region()->pack();
  
    size_t my_archive_size = buffer_top() - buffer_bottom();
  
    if (CDSConfig::is_dumping_static_archive()) {
      _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size;
--- 1187,13 ---
    return UseCompactObjectHeaders ?  CompressedKlassPointers::max_shift() : 0;
  }
  #endif // _LP64
  
  void ArchiveBuilder::relocate_to_requested() {
!   if (!ro_region()->is_packed()) {
+     ro_region()->pack();
+   }
  
    size_t my_archive_size = buffer_top() - buffer_bottom();
  
    if (CDSConfig::is_dumping_static_archive()) {
      _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size;

*** 1392,20 ***
          }
        } else {
          st.print_cr(" - fields (" SIZE_FORMAT " words):", source_oop->size());
          ArchivedFieldPrinter print_field(heap_info, &st, source_oop, buffered_addr);
          InstanceKlass::cast(source_klass)->print_nonstatic_fields(&print_field);
        }
      }
    }
  
    static void log_heap_roots() {
      LogStreamHandle(Trace, cds, map, oops) st;
      if (st.is_enabled()) {
        for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
          st.print("roots[%4d]: ", i);
!         print_oop_with_requested_addr_cr(&st, HeapShared::pending_roots()->at(i));
        }
      }
    }
  
    // The output looks like this. The first number is the requested address. The second number is
--- 1451,30 ---
          }
        } else {
          st.print_cr(" - fields (" SIZE_FORMAT " words):", source_oop->size());
          ArchivedFieldPrinter print_field(heap_info, &st, source_oop, buffered_addr);
          InstanceKlass::cast(source_klass)->print_nonstatic_fields(&print_field);
+ 
+         if (java_lang_Class::is_instance(source_oop)) {
+           st.print(" - signature: ");
+           if (java_lang_Class::is_primitive(source_oop)) {
+             st.print("primitive ??");
+           } else {
+             java_lang_Class::print_signature(source_oop, &st);
+           }
+           st.cr();
+         }
        }
      }
    }
  
    static void log_heap_roots() {
      LogStreamHandle(Trace, cds, map, oops) st;
      if (st.is_enabled()) {
        for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
          st.print("roots[%4d]: ", i);
!         print_oop_with_requested_addr_cr(&st, HeapShared::pending_roots()->at(i).resolve());
        }
      }
    }
  
    // The output looks like this. The first number is the requested address. The second number is

*** 1426,11 ***
        }
        if (source_oop->is_array()) {
          int array_len = arrayOop(source_oop)->length();
          st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
        } else {
!         st->print_cr("%s", source_oop->klass()->external_name());
        }
      }
    }
  #endif // INCLUDE_CDS_JAVA_HEAP
  
--- 1495,16 ---
        }
        if (source_oop->is_array()) {
          int array_len = arrayOop(source_oop)->length();
          st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
        } else {
!         st->print("%s", source_oop->klass()->external_name());
+         if (java_lang_invoke_MethodType::is_instance(source_oop)) {
+           st->print(" ");
+           java_lang_invoke_MethodType::print_signature(source_oop, st);
+         }
+         st->cr();
        }
      }
    }
  #endif // INCLUDE_CDS_JAVA_HEAP
  

*** 1499,16 ***
    // MetaspaceShared::n_regions (internal to hotspot).
    assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
  
    write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
    write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
  
    // Split pointer map into read-write and read-only bitmaps
!   ArchivePtrMarker::initialize_rw_ro_maps(&_rw_ptrmap, &_ro_ptrmap);
  
    size_t bitmap_size_in_bytes;
!   char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::rw_ptrmap(), ArchivePtrMarker::ro_ptrmap(), heap_info,
                                                bitmap_size_in_bytes);
  
    if (heap_info->is_used()) {
      _total_heap_region_size = mapinfo->write_heap_region(heap_info);
    }
--- 1573,20 ---
    // MetaspaceShared::n_regions (internal to hotspot).
    assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
  
    write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
    write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
+   write_region(mapinfo, MetaspaceShared::cc, &_cc_region, /*read_only=*/false,/*allow_exec=*/false);
  
    // Split pointer map into read-write and read-only bitmaps
!   ArchivePtrMarker::initialize_rw_ro_cc_maps(&_rw_ptrmap, &_ro_ptrmap, &_cc_ptrmap);
  
    size_t bitmap_size_in_bytes;
!   char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::rw_ptrmap(),
+                                               ArchivePtrMarker::ro_ptrmap(),
+                                               ArchivePtrMarker::cc_ptrmap(),
+                                               heap_info,
                                                bitmap_size_in_bytes);
  
    if (heap_info->is_used()) {
      _total_heap_region_size = mapinfo->write_heap_region(heap_info);
    }

*** 1550,10 ***
--- 1628,11 ---
                               _total_heap_region_size;
    const double total_u_perc = percent_of(total_bytes, total_reserved);
  
    _rw_region.print(total_reserved);
    _ro_region.print(total_reserved);
+   _cc_region.print(total_reserved);
  
    print_bitmap_region_stats(bitmap_used, total_reserved);
  
    if (heap_info->is_used()) {
      print_heap_region_stats(heap_info, total_reserved);
< prev index next >