< prev index next >

src/hotspot/share/cds/metaspaceShared.cpp

Print this page
*** 20,10 ***
--- 20,12 ---
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   *
   */
  
+ #include "cds/aotCacheAccess.hpp"
+ #include "cds/aotClassInitializer.hpp"
  #include "cds/aotArtifactFinder.hpp"
  #include "cds/aotClassInitializer.hpp"
  #include "cds/aotClassLinker.hpp"
  #include "cds/aotClassLocation.hpp"
  #include "cds/aotConstantPoolResolver.hpp"

*** 60,10 ***
--- 62,12 ---
  #include "classfile/systemDictionaryShared.hpp"
  #include "classfile/vmClasses.hpp"
  #include "classfile/vmSymbols.hpp"
  #include "code/aotCodeCache.hpp"
  #include "code/codeCache.hpp"
+ #include "compiler/compileBroker.hpp"
+ #include "compiler/precompiler.hpp"
  #include "gc/shared/gcVMOperations.hpp"
  #include "interpreter/bytecodeStream.hpp"
  #include "interpreter/bytecodes.hpp"
  #include "jvm_io.h"
  #include "logging/log.hpp"

*** 77,15 ***
--- 81,17 ---
  #include "memory/universe.hpp"
  #include "nmt/memTracker.hpp"
  #include "oops/compressedKlass.hpp"
  #include "oops/instanceMirrorKlass.hpp"
  #include "oops/klass.inline.hpp"
+ #include "oops/method.inline.hpp"
  #include "oops/objArrayOop.hpp"
  #include "oops/oop.inline.hpp"
  #include "oops/oopHandle.hpp"
  #include "oops/trainingData.hpp"
  #include "prims/jvmtiExport.hpp"
+ #include "prims/whitebox.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/globals.hpp"
  #include "runtime/globals_extension.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/javaCalls.hpp"

*** 93,10 ***
--- 99,11 ---
  #include "runtime/safepointVerifiers.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/vmOperations.hpp"
  #include "runtime/vmThread.hpp"
  #include "sanitizers/leak.hpp"
+ #include "services/management.hpp"
  #include "utilities/align.hpp"
  #include "utilities/bitMap.inline.hpp"
  #include "utilities/defaultStream.hpp"
  #include "utilities/macros.hpp"
  #include "utilities/ostream.hpp"

*** 111,10 ***
--- 118,12 ---
  void* MetaspaceShared::_shared_metaspace_static_top = nullptr;
  intx MetaspaceShared::_relocation_delta;
  char* MetaspaceShared::_requested_base_address;
  Array<Method*>* MetaspaceShared::_archived_method_handle_intrinsics = nullptr;
  bool MetaspaceShared::_use_optimized_module_handling = true;
+ int volatile MetaspaceShared::_preimage_static_archive_dumped = 0;
+ jlong MetaspaceShared::_preimage_static_archive_recording_duration = 0;
  
  // The CDS archive is divided into the following regions:
  //     rw  - read-write metadata
  //     ro  - read-only metadata and read-only tables
  //     hp  - heap region

*** 291,10 ***
--- 300,25 ---
    return aligned_base;
  }
  
  void MetaspaceShared::initialize_for_static_dump() {
    assert(CDSConfig::is_dumping_static_archive(), "sanity");
+ 
+   if (CDSConfig::is_dumping_preimage_static_archive() || CDSConfig::is_dumping_final_static_archive()) {
+     if (!((UseG1GC || UseParallelGC || UseSerialGC || UseEpsilonGC || UseShenandoahGC) && UseCompressedClassPointers)) {
+       const char* error;
+       if (CDSConfig::is_dumping_preimage_static_archive()) {
+         error = "Cannot create the AOT configuration file";
+       } else {
+         error = "Cannot create the AOT cache";
+       }
+ 
+       vm_exit_during_initialization(error,
+                                     "UseCompressedClassPointers must be enabled, and collector must be G1, Parallel, Serial, Epsilon, or Shenandoah");
+     }
+   }
+ 
    aot_log_info(aot)("Core region alignment: %zu", core_region_alignment());
    // The max allowed size for CDS archive. We use this to limit SharedBaseAddress
    // to avoid address space wrap around.
    size_t cds_max;
    const size_t reserve_alignment = core_region_alignment();

*** 735,10 ***
--- 759,13 ---
  };
  
  // Check if we can eagerly link this class at dump time, so we can avoid the
  // runtime linking overhead (especially verification)
  bool MetaspaceShared::may_be_eagerly_linked(InstanceKlass* ik) {
+   if (CDSConfig::preserve_all_dumptime_verification_states(ik)) {
+     assert(ik->can_be_verified_at_dumptime(), "sanity");
+   }
    if (!ik->can_be_verified_at_dumptime()) {
      // For old classes, try to leave them in the unlinked state, so
      // we can still store them in the archive. They must be
      // linked/verified at runtime.
      return false;

*** 757,10 ***
--- 784,14 ---
  
  void MetaspaceShared::link_shared_classes(TRAPS) {
    AOTClassLinker::initialize();
    AOTClassInitializer::init_test_class(CHECK);
  
+   if (CDSConfig::is_dumping_final_static_archive()) {
+     FinalImageRecipes::apply_recipes(CHECK);
+   }
+ 
    while (true) {
      ResourceMark rm(THREAD);
      CollectClassesForLinking collect_classes;
      bool has_linked = false;
      const GrowableArray<OopHandle>* mirrors = collect_classes.mirrors();

*** 768,10 ***
--- 799,13 ---
        OopHandle mirror = mirrors->at(i);
        InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve()));
        if (may_be_eagerly_linked(ik)) {
          has_linked |= try_link_class(THREAD, ik);
        }
+       if (CDSConfig::is_dumping_heap() && ik->is_linked() && !ik->is_initialized()) {
+         AOTClassInitializer::maybe_preinit_class(ik, CHECK);
+       }
      }
  
      if (!has_linked) {
        break;
      }

*** 786,29 ***
      const GrowableArray<OopHandle>* mirrors = collect_classes.mirrors();
      for (int i = 0; i < mirrors->length(); i++) {
        OopHandle mirror = mirrors->at(i);
        InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve()));
        AOTConstantPoolResolver::preresolve_string_cp_entries(ik, CHECK);
      }
    }
- 
-   if (CDSConfig::is_dumping_final_static_archive()) {
-     FinalImageRecipes::apply_recipes(CHECK);
-   }
  }
  
  // Preload classes from a list, populate the shared spaces and dump to a
  // file.
  void MetaspaceShared::preload_and_dump(TRAPS) {
    CDSConfig::DumperThreadMark dumper_thread_mark(THREAD);
    ResourceMark rm(THREAD);
!  HandleMark hm(THREAD);
  
!  if (CDSConfig::is_dumping_final_static_archive() && AOTPrintTrainingInfo) {
!    tty->print_cr("==================== archived_training_data ** before dumping ====================");
!    TrainingData::print_archived_training_data_on(tty);
!  }
  
    StaticArchiveBuilder builder;
    preload_and_dump_impl(builder, THREAD);
    if (HAS_PENDING_EXCEPTION) {
      if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {
--- 820,28 ---
      const GrowableArray<OopHandle>* mirrors = collect_classes.mirrors();
      for (int i = 0; i < mirrors->length(); i++) {
        OopHandle mirror = mirrors->at(i);
        InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve()));
        AOTConstantPoolResolver::preresolve_string_cp_entries(ik, CHECK);
+       if (CDSConfig::is_dumping_preimage_static_archive()) {
+         FinalImageRecipes::add_reflection_data_flags(ik, CHECK);
+       }
      }
    }
  }
  
  // Preload classes from a list, populate the shared spaces and dump to a
  // file.
  void MetaspaceShared::preload_and_dump(TRAPS) {
    CDSConfig::DumperThreadMark dumper_thread_mark(THREAD);
    ResourceMark rm(THREAD);
!   HandleMark hm(THREAD);
  
!   if (CDSConfig::is_dumping_final_static_archive() && AOTPrintTrainingInfo) {
!     tty->print_cr("==================== archived_training_data ** before dumping ====================");
!     TrainingData::print_archived_training_data_on(tty);
!   }
  
    StaticArchiveBuilder builder;
    preload_and_dump_impl(builder, THREAD);
    if (HAS_PENDING_EXCEPTION) {
      if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {

*** 835,15 ***
        // to the JLI launcher, as the launcher will fail when trying to
        // run the main class, which is not what we want.
        struct stat st;
        if (os::stat(AOTCache, &st) != 0) {
          tty->print_cr("AOTCache creation failed: %s", AOTCache);
-         vm_exit(0);
        } else {
          tty->print_cr("AOTCache creation is complete: %s " INT64_FORMAT " bytes", AOTCache, (int64_t)(st.st_size));
-         vm_exit(0);
        }
      }
    }
  }
  
  #if INCLUDE_CDS_JAVA_HEAP && defined(_LP64)
--- 868,14 ---
        // to the JLI launcher, as the launcher will fail when trying to
        // run the main class, which is not what we want.
        struct stat st;
        if (os::stat(AOTCache, &st) != 0) {
          tty->print_cr("AOTCache creation failed: %s", AOTCache);
        } else {
          tty->print_cr("AOTCache creation is complete: %s " INT64_FORMAT " bytes", AOTCache, (int64_t)(st.st_size));
        }
+       vm_direct_exit(0);
      }
    }
  }
  
  #if INCLUDE_CDS_JAVA_HEAP && defined(_LP64)

*** 918,11 ***
--- 950,36 ---
  
    // Exercise FileSystem and URL code
    CDSProtectionDomain::to_file_URL("dummy.jar", Handle(), CHECK);
  }
  
+ bool MetaspaceShared::is_recording_preimage_static_archive() {
+   if (CDSConfig::is_dumping_preimage_static_archive()) {
+       return _preimage_static_archive_dumped == 0;
+   }
+   return false;
+ }
+ 
+ jlong MetaspaceShared::get_preimage_static_archive_recording_duration() {
+   if (CDSConfig::is_dumping_preimage_static_archive()) {
+     if (_preimage_static_archive_recording_duration == 0) {
+       // The recording has not yet finished so return the current elapsed time.
+       return Management::ticks_to_ms(os::elapsed_counter());
+     }
+     return _preimage_static_archive_recording_duration;
+   }
+   return 0;
+ }
+ 
  void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS) {
+   if (CDSConfig::is_dumping_preimage_static_archive()) {
+     if (Atomic::cmpxchg(&_preimage_static_archive_dumped, 0, 1) != 0) {
+       return;
+     }
+     _preimage_static_archive_recording_duration = Management::ticks_to_ms(os::elapsed_counter());
+   }
+ 
    if (CDSConfig::is_dumping_classic_static_archive()) {
      // We are running with -Xshare:dump
      preload_classes(CHECK);
  
      if (SharedArchiveConfigFile) {

*** 985,10 ***
--- 1042,14 ---
      if (CDSConfig::is_dumping_full_module_graph()) {
        ClassLoaderDataShared::ensure_module_entry_tables_exist();
        HeapShared::reset_archived_object_states(CHECK);
      }
  
+     if (ArchiveLoaderLookupCache) {
+       SystemDictionaryShared::create_loader_positive_lookup_cache(CHECK);
+     }
+ 
      AOTReferenceObjSupport::initialize(CHECK);
      AOTReferenceObjSupport::stabilize_cached_reference_objects(CHECK);
  
      if (CDSConfig::is_initing_classes_at_dump_time()) {
        // java.lang.Class::reflectionFactory cannot be archived yet. We set this field

*** 1013,23 ***
    }
  #endif
  
    VM_PopulateDumpSharedSpace op(builder);
    VMThread::execute(&op);
  
!   if (AOTCodeCache::is_on_for_dump() && CDSConfig::is_dumping_final_static_archive()) {
!     CDSConfig::enable_dumping_aot_code();
!     {
!       builder.start_ac_region();
!       // Write the contents to AOT code region and close AOTCodeCache before packing the region
!       AOTCodeCache::close();
!       builder.end_ac_region();
      }
-     CDSConfig::disable_dumping_aot_code();
    }
  
!   bool status = write_static_archive(&builder, op.map_info(), op.heap_info());
    if (status && CDSConfig::is_dumping_preimage_static_archive()) {
      tty->print_cr("%s AOTConfiguration recorded: %s",
                    CDSConfig::has_temp_aot_config_file() ? "Temporary" : "", AOTConfiguration);
      if (CDSConfig::is_single_command_training()) {
        fork_and_dump_final_static_archive(CHECK);
--- 1074,40 ---
    }
  #endif
  
    VM_PopulateDumpSharedSpace op(builder);
    VMThread::execute(&op);
+   FileMapInfo* mapinfo = op.map_info();
+   ArchiveHeapInfo* heap_info = op.heap_info();
  
!   if (CDSConfig::is_dumping_final_static_archive()) {
!     if (AOTCodeCache::is_caching_enabled()) {
!       if (log_is_enabled(Info, cds, jit)) {
!         AOTCacheAccess::test_heap_access_api();
!       }
! 
!       // We have just created the final image. Let's run the AOT compiler
+       if (AOTPrintTrainingInfo) {
+         tty->print_cr("==================== archived_training_data ** after dumping ====================");
+         TrainingData::print_archived_training_data_on(tty);
+       }
+ 
+       CDSConfig::enable_dumping_aot_code();
+       {
+         builder.start_ac_region();
+         if (AOTCodeCache::is_dumping_code()) {
+           Precompiler::compile_cached_code(&builder, CHECK);
+         }
+         // Write the contents to aot code region and close AOTCodeCache before packing the region
+         AOTCodeCache::close();
+         builder.end_ac_region();
+       }
+       CDSConfig::disable_dumping_aot_code();
      }
    }
  
!   bool status = write_static_archive(&builder, mapinfo, heap_info);
    if (status && CDSConfig::is_dumping_preimage_static_archive()) {
      tty->print_cr("%s AOTConfiguration recorded: %s",
                    CDSConfig::has_temp_aot_config_file() ? "Temporary" : "", AOTConfiguration);
      if (CDSConfig::is_single_command_training()) {
        fork_and_dump_final_static_archive(CHECK);

*** 1228,11 ***
  }
  
  void VM_PopulateDumpSharedSpace::dump_java_heap_objects() {
    if (CDSConfig::is_dumping_heap()) {
      HeapShared::write_heap(&_heap_info);
!   } else {
      CDSConfig::log_reasons_for_not_dumping_heap();
    }
  }
  
  void MetaspaceShared::set_shared_metaspace_range(void* base, void *static_top, void* top) {
--- 1306,11 ---
  }
  
  void VM_PopulateDumpSharedSpace::dump_java_heap_objects() {
    if (CDSConfig::is_dumping_heap()) {
      HeapShared::write_heap(&_heap_info);
!   } else if (!CDSConfig::is_dumping_preimage_static_archive()) {
      CDSConfig::log_reasons_for_not_dumping_heap();
    }
  }
  
  void MetaspaceShared::set_shared_metaspace_range(void* base, void *static_top, void* top) {

*** 1286,10 ***
--- 1364,14 ---
    LogLevelType level = (!CDSConfig::is_using_archive() || CDSConfig::is_using_only_default_archive()) ?
                          LogLevel::Info : LogLevel::Error;
    LogStream ls_cds(level, LogTagSetMapping<LOG_TAGS(cds)>::tagset());
  
    LogStream& ls = CDSConfig::new_aot_flags_used() ? ls_aot : ls_cds;
+   if (!ls.is_enabled()) {
+     return;
+   }
+ 
    va_list ap;
    va_start(ap, format);
  
    static bool printed_error = false;
    if (!printed_error) { // No need for locks. Loading error checks happen only in main thread.

*** 1320,11 ***
  
  void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
    assert(CDSConfig::is_using_archive(), "Must be called when UseSharedSpaces is enabled");
    MapArchiveResult result = MAP_ARCHIVE_OTHER_FAILURE;
  
!   FileMapInfo* static_mapinfo = open_static_archive();
    FileMapInfo* dynamic_mapinfo = nullptr;
  
    if (static_mapinfo != nullptr) {
      aot_log_info(aot)("Core region alignment: %zu", static_mapinfo->core_region_alignment());
      dynamic_mapinfo = open_dynamic_archive();
--- 1402,11 ---
  
  void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
    assert(CDSConfig::is_using_archive(), "Must be called when UseSharedSpaces is enabled");
    MapArchiveResult result = MAP_ARCHIVE_OTHER_FAILURE;
  
!   FileMapInfo* static_mapinfo = FileMapInfo::current_info();
    FileMapInfo* dynamic_mapinfo = nullptr;
  
    if (static_mapinfo != nullptr) {
      aot_log_info(aot)("Core region alignment: %zu", static_mapinfo->core_region_alignment());
      dynamic_mapinfo = open_dynamic_archive();

*** 1383,23 ***
    if (dynamic_mapinfo != nullptr && !dynamic_mapinfo->is_mapped()) {
      has_failed = true;
      delete dynamic_mapinfo;
    }
    if (RequireSharedSpaces && has_failed) {
        MetaspaceShared::unrecoverable_loading_error("Unable to map shared spaces");
    }
  }
  
! FileMapInfo* MetaspaceShared::open_static_archive() {
    const char* static_archive = CDSConfig::input_static_archive_path();
    assert(static_archive != nullptr, "sanity");
    FileMapInfo* mapinfo = new FileMapInfo(static_archive, true);
    if (!mapinfo->open_as_input()) {
      delete(mapinfo);
!     return nullptr;
    }
-   return mapinfo;
  }
  
  FileMapInfo* MetaspaceShared::open_dynamic_archive() {
    if (CDSConfig::is_dumping_dynamic_archive()) {
      return nullptr;
--- 1465,29 ---
    if (dynamic_mapinfo != nullptr && !dynamic_mapinfo->is_mapped()) {
      has_failed = true;
      delete dynamic_mapinfo;
    }
    if (RequireSharedSpaces && has_failed) {
+     // static archive mapped but dynamic archive failed
        MetaspaceShared::unrecoverable_loading_error("Unable to map shared spaces");
    }
  }
  
! // This is called very early at VM start up to get the size of the cached_code region
+ void MetaspaceShared::open_static_archive() {
+   if (!UseSharedSpaces) { // FIXME -- is this still needed??
+     return;
+   }
    const char* static_archive = CDSConfig::input_static_archive_path();
    assert(static_archive != nullptr, "sanity");
    FileMapInfo* mapinfo = new FileMapInfo(static_archive, true);
    if (!mapinfo->open_as_input()) {
      delete(mapinfo);
!   } else {
+     FileMapRegion* r = mapinfo->region_at(MetaspaceShared::ac);
+     AOTCacheAccess::set_aot_code_region_size(r->used_aligned());
    }
  }
  
  FileMapInfo* MetaspaceShared::open_dynamic_archive() {
    if (CDSConfig::is_dumping_dynamic_archive()) {
      return nullptr;

*** 1881,10 ***
--- 1969,14 ---
    assert(CDSConfig::is_using_archive(), "must be runtime");
    if (mapinfo == nullptr) {
      return MAP_ARCHIVE_SUCCESS; // The dynamic archive has not been specified. No error has happened -- trivially succeeded.
    }
  
+   if (!mapinfo->validate_aot_class_linking()) {
+     return MAP_ARCHIVE_OTHER_FAILURE;
+   }
+ 
    mapinfo->set_is_mapped(false);
    if (mapinfo->core_region_alignment() != (size_t)core_region_alignment()) {
      report_loading_error("Unable to map CDS archive -- core_region_alignment() expected: %zu"
                           " actual: %zu", mapinfo->core_region_alignment(), core_region_alignment());
      return MAP_ARCHIVE_OTHER_FAILURE;

*** 2012,14 ***
        SystemDictionaryShared::print_shared_archive(tty, false/*dynamic*/);
      }
  
      TrainingData::print_archived_training_data_on(tty);
  
!     if (AOTCodeCache::is_on_for_use()) {
-       tty->print_cr("\n\nAOT Code");
-       AOTCodeCache::print_on(tty);
-     }
  
      // collect shared symbols and strings
      CountSharedSymbols cl;
      SymbolTable::shared_symbols_do(&cl);
      tty->print_cr("Number of shared symbols: %d", cl.total());
--- 2104,11 ---
        SystemDictionaryShared::print_shared_archive(tty, false/*dynamic*/);
      }
  
      TrainingData::print_archived_training_data_on(tty);
  
!     AOTCodeCache::print_on(tty);
  
      // collect shared symbols and strings
      CountSharedSymbols cl;
      SymbolTable::shared_symbols_do(&cl);
      tty->print_cr("Number of shared symbols: %d", cl.total());
< prev index next >