< prev index next >

src/hotspot/share/cds/cdsConfig.cpp

Print this page
*** 23,17 ***
--- 23,23 ---
   */
  
  #include "cds/aotLogging.hpp"
  #include "cds/archiveHeapLoader.hpp"
  #include "cds/cdsConfig.hpp"
+ #include "cds/cds_globals.hpp"
  #include "cds/classListWriter.hpp"
  #include "cds/filemap.hpp"
  #include "cds/heapShared.hpp"
+ #include "cds/metaspaceShared.hpp"
  #include "classfile/classLoaderDataShared.hpp"
  #include "classfile/moduleEntry.hpp"
+ #include "classfile/systemDictionaryShared.hpp"
+ #include "code/aotCodeCache.hpp"
+ #include "compiler/compilerDefinitions.inline.hpp"
  #include "include/jvm_io.h"
  #include "logging/log.hpp"
+ #include "prims/jvmtiExport.hpp"
  #include "memory/universe.hpp"
  #include "prims/jvmtiAgentList.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/globals_extension.hpp"
  #include "runtime/java.hpp"

*** 49,10 ***
--- 55,13 ---
  bool CDSConfig::_is_dumping_full_module_graph = true;
  bool CDSConfig::_is_using_full_module_graph = true;
  bool CDSConfig::_has_aot_linked_classes = false;
  bool CDSConfig::_is_single_command_training = false;
  bool CDSConfig::_has_temp_aot_config_file = false;
+ bool CDSConfig::_is_loading_packages = false;
+ bool CDSConfig::_is_loading_protection_domains = false;
+ bool CDSConfig::_is_security_manager_allowed = false;
  bool CDSConfig::_old_cds_flags_used = false;
  bool CDSConfig::_new_aot_flags_used = false;
  bool CDSConfig::_disable_heap_dumping = false;
  
  const char* CDSConfig::_default_archive_path = nullptr;

*** 66,11 ***
    assert(Universe::is_fully_initialized(), "status is finalized only after Universe is initialized");
    return (is_dumping_archive()              ? IS_DUMPING_ARCHIVE : 0) |
           (is_dumping_method_handles()       ? IS_DUMPING_METHOD_HANDLES : 0) |
           (is_dumping_static_archive()       ? IS_DUMPING_STATIC_ARCHIVE : 0) |
           (is_logging_lambda_form_invokers() ? IS_LOGGING_LAMBDA_FORM_INVOKERS : 0) |
!          (is_using_archive()                ? IS_USING_ARCHIVE : 0);
  }
  
  DEBUG_ONLY(static bool _cds_ergo_initialize_started = false);
  
  void CDSConfig::ergo_initialize() {
--- 75,15 ---
    assert(Universe::is_fully_initialized(), "status is finalized only after Universe is initialized");
    return (is_dumping_archive()              ? IS_DUMPING_ARCHIVE : 0) |
           (is_dumping_method_handles()       ? IS_DUMPING_METHOD_HANDLES : 0) |
           (is_dumping_static_archive()       ? IS_DUMPING_STATIC_ARCHIVE : 0) |
           (is_logging_lambda_form_invokers() ? IS_LOGGING_LAMBDA_FORM_INVOKERS : 0) |
!          (is_using_archive()                ? IS_USING_ARCHIVE : 0) |
+          (is_dumping_heap()                 ? IS_DUMPING_HEAP : 0) |
+          (is_logging_dynamic_proxies()      ? IS_LOGGING_DYNAMIC_PROXIES : 0) |
+          (is_dumping_packages()             ? IS_DUMPING_PACKAGES : 0) |
+          (is_dumping_protection_domains()   ? IS_DUMPING_PROTECTION_DOMAINS : 0);
  }
  
  DEBUG_ONLY(static bool _cds_ergo_initialize_started = false);
  
  void CDSConfig::ergo_initialize() {

*** 101,10 ***
--- 114,30 ---
    }
  
    if (!is_dumping_heap()) {
      _is_dumping_full_module_graph = false;
    }
+ 
+ #ifdef _LP64
+   //
+   // By default, when using AOTClassLinking, use the CompressedOops::HeapBasedNarrowOop
+   // mode so that AOT code can be always work regardless of runtime heap range.
+   //
+   // If you are *absolutely sure* that the CompressedOops::mode() will be the same
+   // between training and production runs (e.g., if you specify -Xmx128m for
+   // both training and production runs, and you know the OS will always reserve
+   // the heap under 4GB), you can explicitly disable this with:
+   //     java -XX:+UnlockDiagnosticVMOptions -XX:-UseCompatibleCompressedOops ...
+   // However, this is risky and there's a chance that the production run will be slower
+   // than expected because it is unable to load the AOT code cache.
+   //
+   if (UseCompressedOops && AOTCodeCache::is_caching_enabled()) {
+     FLAG_SET_ERGO_IF_DEFAULT(UseCompatibleCompressedOops, true);
+   } else if (!FLAG_IS_DEFAULT(UseCompatibleCompressedOops)) {
+     FLAG_SET_ERGO(UseCompatibleCompressedOops, false);
+   }
+ #endif // _LP64
  }
  
  const char* CDSConfig::default_archive_path() {
    // The path depends on UseCompressedOops, etc, which are set by GC ergonomics just
    // before CDSConfig::ergo_initialize() is called.

*** 278,13 ***
--- 311,25 ---
        }
      }
    }
  }
  
+ static char* bad_module_prop_key   = nullptr;
+ static char* bad_module_prop_value = nullptr;
+ 
  void CDSConfig::check_internal_module_property(const char* key, const char* value) {
    if (Arguments::is_incompatible_cds_internal_module_property(key)) {
      stop_using_optimized_module_handling();
+     if (bad_module_prop_key == nullptr) {
+       // We don't want to print an unconditional warning here, as we are still processing the command line.
+       // A later argument may specify something like -Xshare:off, which makes such a warning irrelevant.
+       //
+       // Instead, we save the info so we can warn when necessary: we are doing it only during AOT Cache
+       // creation for now, but could add it to other places.
+       bad_module_prop_key   = os::strdup(key);
+       bad_module_prop_value = os::strdup(value);
+     }
      aot_log_info(aot)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
    }
  }
  
  void CDSConfig::check_incompatible_property(const char* key, const char* value) {

*** 301,10 ***
--- 346,16 ---
        aot_log_info(aot)("full module graph: disabled due to incompatible property: %s=%s", key, value);
        break;
      }
    }
  
+   // Match the logic in java/lang/System.java, but we need to know this before the System class is initialized.
+   if (strcmp(key, "java.security.manager") == 0) {
+     if (strcmp(value, "disallowed") != 0) {
+       _is_security_manager_allowed = true;
+     }
+   }
  }
  
  // Returns any JVM command-line option, such as "--patch-module", that's not supported by CDS.
  static const char* find_any_unsupported_module_option() {
    // Note that arguments.cpp has translated the command-line options into properties. If we find an

*** 619,17 ***
    }
  
    setup_compiler_args();
  
    if (AOTClassLinking) {
!     // If AOTClassLinking is specified, enable all AOT optimizations by default.
      FLAG_SET_ERGO_IF_DEFAULT(AOTInvokeDynamicLinking, true);
    } else {
!     // AOTInvokeDynamicLinking depends on AOTClassLinking.
      FLAG_SET_ERGO(AOTInvokeDynamicLinking, false);
    }
  
    if (is_dumping_static_archive()) {
      if (is_dumping_preimage_static_archive() || is_dumping_final_static_archive()) {
        // Don't tweak execution mode
      } else if (!mode_flag_cmd_line) {
        // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive.
--- 670,38 ---
    }
  
    setup_compiler_args();
  
    if (AOTClassLinking) {
!     // If AOTClassLinking is specified, enable all these optimizations by default.
      FLAG_SET_ERGO_IF_DEFAULT(AOTInvokeDynamicLinking, true);
+     FLAG_SET_ERGO_IF_DEFAULT(ArchiveDynamicProxies, true);
+     FLAG_SET_ERGO_IF_DEFAULT(ArchiveLoaderLookupCache, true);
+     FLAG_SET_ERGO_IF_DEFAULT(ArchivePackages, true);
+     FLAG_SET_ERGO_IF_DEFAULT(ArchiveProtectionDomains, true);
+     FLAG_SET_ERGO_IF_DEFAULT(ArchiveReflectionData, true);
    } else {
!     // All of these *might* depend on AOTClassLinking. Better be safe than sorry.
      FLAG_SET_ERGO(AOTInvokeDynamicLinking, false);
+     FLAG_SET_ERGO(ArchiveDynamicProxies, false);
+     FLAG_SET_ERGO(ArchiveLoaderLookupCache, false);
+     FLAG_SET_ERGO(ArchivePackages, false);
+     FLAG_SET_ERGO(ArchiveProtectionDomains, false);
+     FLAG_SET_ERGO(ArchiveReflectionData, false);
+ 
+     if (CDSConfig::is_dumping_archive()) {
+       FLAG_SET_ERGO(AOTRecordTraining, false);
+       FLAG_SET_ERGO(AOTReplayTraining, false);
+       AOTCodeCache::disable_caching();
+     }
    }
  
+ #ifdef _WINDOWS
+   // This optimization is not working on Windows for some reason. See JDK-8338604.
+   FLAG_SET_ERGO(ArchiveReflectionData, false);
+ #endif
+ 
    if (is_dumping_static_archive()) {
      if (is_dumping_preimage_static_archive() || is_dumping_final_static_archive()) {
        // Don't tweak execution mode
      } else if (!mode_flag_cmd_line) {
        // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive.

*** 687,32 ***
        BytecodeVerificationRemote = true;
        aot_log_info(aot)("All non-system classes will be verified (-Xverify:remote) during CDS dump time.");
      }
    }
  
    return true;
  }
  
  void CDSConfig::setup_compiler_args() {
!   // AOT profiles are supported only in the JEP 483 workflow.
!   bool can_dump_profiles = AOTClassLinking && new_aot_flags_used();
  
!   if (is_dumping_preimage_static_archive() && can_dump_profiles) {
      // JEP 483 workflow -- training
      FLAG_SET_ERGO_IF_DEFAULT(AOTRecordTraining, true);
      FLAG_SET_ERGO(AOTReplayTraining, false);
!   } else if (is_dumping_final_static_archive() && can_dump_profiles) {
      // JEP 483 workflow -- assembly
      FLAG_SET_ERGO(AOTRecordTraining, false);
      FLAG_SET_ERGO_IF_DEFAULT(AOTReplayTraining, true);
!   } else if (is_using_archive() && new_aot_flags_used()) {
      // JEP 483 workflow -- production
      FLAG_SET_ERGO(AOTRecordTraining, false);
      FLAG_SET_ERGO_IF_DEFAULT(AOTReplayTraining, true);
    } else {
      FLAG_SET_ERGO(AOTReplayTraining, false);
      FLAG_SET_ERGO(AOTRecordTraining, false);
    }
  }
  
  void CDSConfig::prepare_for_dumping() {
    assert(CDSConfig::is_dumping_archive(), "sanity");
--- 759,48 ---
        BytecodeVerificationRemote = true;
        aot_log_info(aot)("All non-system classes will be verified (-Xverify:remote) during CDS dump time.");
      }
    }
  
+   if (AOTClassLinking) {
+     if (is_dumping_final_static_archive() && !is_dumping_full_module_graph()) {
+       if (bad_module_prop_key != nullptr) {
+         log_warning(cds)("optimized module handling/full module graph: disabled due to incompatible property: %s=%s",
+                          bad_module_prop_key, bad_module_prop_value);
+       }
+       vm_exit_during_initialization("AOT cache cannot be created because AOTClassLinking is enabled but full module graph is disabled");
+     }
+   }
+ 
    return true;
  }
  
  void CDSConfig::setup_compiler_args() {
!   // AOT profiles and AOT-compiled methods are supported only in the JEP 483 workflow.
!   bool can_dump_profile_and_compiled_code = !CompilerConfig::is_interpreter_only() && AOTClassLinking && new_aot_flags_used();
+   bool can_use_profile_and_compiled_code = !CompilerConfig::is_interpreter_only() && new_aot_flags_used();
  
!   if (is_dumping_preimage_static_archive() && can_dump_profile_and_compiled_code) {
      // JEP 483 workflow -- training
      FLAG_SET_ERGO_IF_DEFAULT(AOTRecordTraining, true);
      FLAG_SET_ERGO(AOTReplayTraining, false);
!     AOTCodeCache::disable_caching();
+   } else if (is_dumping_final_static_archive() && can_dump_profile_and_compiled_code) {
      // JEP 483 workflow -- assembly
      FLAG_SET_ERGO(AOTRecordTraining, false);
      FLAG_SET_ERGO_IF_DEFAULT(AOTReplayTraining, true);
!     AOTCodeCache::enable_caching();
+     disable_dumping_aot_code(); // Cannot dump aot code until metadata and heap are dumped.
+   } else if (is_using_archive() && can_use_profile_and_compiled_code) {
      // JEP 483 workflow -- production
      FLAG_SET_ERGO(AOTRecordTraining, false);
      FLAG_SET_ERGO_IF_DEFAULT(AOTReplayTraining, true);
+     AOTCodeCache::enable_caching();
    } else {
      FLAG_SET_ERGO(AOTReplayTraining, false);
      FLAG_SET_ERGO(AOTRecordTraining, false);
+     AOTCodeCache::disable_caching();
    }
  }
  
  void CDSConfig::prepare_for_dumping() {
    assert(CDSConfig::is_dumping_archive(), "sanity");

*** 750,10 ***
--- 838,14 ---
  
  bool CDSConfig::is_dumping_preimage_static_archive() {
    return _is_dumping_preimage_static_archive;
  }
  
+ bool CDSConfig::is_dumping_preimage_static_archive_with_triggers() {
+   return (!FLAG_IS_DEFAULT(AOTEndTrainingOnMethodEntry)) && is_dumping_preimage_static_archive();
+ }
+ 
  bool CDSConfig::is_dumping_final_static_archive() {
    return _is_dumping_final_static_archive;
  }
  
  void CDSConfig::enable_dumping_dynamic_archive(const char* output_path) {

*** 771,10 ***
--- 863,24 ---
  bool CDSConfig::allow_only_single_java_thread() {
    // See comments in JVM_StartThread()
    return is_dumping_classic_static_archive() || is_dumping_final_static_archive();
  }
  
+ bool CDSConfig::is_logging_dynamic_proxies() {
+   return ClassListWriter::is_enabled() || is_dumping_preimage_static_archive();
+ }
+ 
+ // Preserve all states that were examined used during dumptime verification, such
+ // that the verification result (pass or fail) cannot be changed at runtime.
+ //
+ // For example, if the verification of ik requires that class A must be a subtype of B,
+ // then this relationship between A and B cannot be changed at runtime. I.e., the app
+ // cannot load alternative versions of A and B such that A is not a subtype of B.
+ bool CDSConfig::preserve_all_dumptime_verification_states(const InstanceKlass* ik) {
+   return is_dumping_aot_linked_classes() && SystemDictionaryShared::is_builtin(ik);
+ }
+ 
  bool CDSConfig::is_using_archive() {
    return UseSharedSpaces;
  }
  
  bool CDSConfig::is_using_only_default_archive() {

*** 784,11 ***
           strcmp(input_static_archive_path(), default_archive_path()) == 0 &&
           input_dynamic_archive_path() == nullptr;
  }
  
  bool CDSConfig::is_logging_lambda_form_invokers() {
!   return ClassListWriter::is_enabled() || is_dumping_dynamic_archive();
  }
  
  bool CDSConfig::is_dumping_regenerated_lambdaform_invokers() {
    if (is_dumping_final_static_archive()) {
      // No need to regenerate -- the lambda form invokers should have been regenerated
--- 890,11 ---
           strcmp(input_static_archive_path(), default_archive_path()) == 0 &&
           input_dynamic_archive_path() == nullptr;
  }
  
  bool CDSConfig::is_logging_lambda_form_invokers() {
!   return ClassListWriter::is_enabled() || is_dumping_dynamic_archive() || is_dumping_preimage_static_archive();
  }
  
  bool CDSConfig::is_dumping_regenerated_lambdaform_invokers() {
    if (is_dumping_final_static_archive()) {
      // No need to regenerate -- the lambda form invokers should have been regenerated

*** 960,10 ***
--- 1066,14 ---
    // Make sure we have the exact same module graph as in the assembly phase, or else
    // some aot-linked classes may not be visible so cannot be loaded.
    return is_using_full_module_graph() && _has_aot_linked_classes;
  }
  
+ bool CDSConfig::is_dumping_dynamic_proxies() {
+   return is_dumping_full_module_graph() && is_dumping_invokedynamic() && ArchiveDynamicProxies;
+ }
+ 
  void CDSConfig::set_has_aot_linked_classes(bool has_aot_linked_classes) {
    _has_aot_linked_classes |= has_aot_linked_classes;
  }
  
  bool CDSConfig::is_initing_classes_at_dump_time() {

*** 974,10 ***
--- 1084,41 ---
    // Requires is_dumping_aot_linked_classes(). Otherwise the classes of some archived heap
    // objects used by the archive indy callsites may be replaced at runtime.
    return AOTInvokeDynamicLinking && is_dumping_aot_linked_classes() && is_dumping_heap();
  }
  
+ bool CDSConfig::is_dumping_packages() {
+   return ArchivePackages && is_dumping_heap();
+ }
+ 
+ bool CDSConfig::is_loading_packages() {
+   return UseSharedSpaces && is_using_full_module_graph() && _is_loading_packages;
+ }
+ 
+ bool CDSConfig::is_dumping_protection_domains() {
+   if (_is_security_manager_allowed) {
+     // For sanity, don't archive PDs. TODO: can this be relaxed?
+     return false;
+   }
+   // Archived PDs for the modules will reference their java.lang.Module, which must
+   // also be archived.
+   return ArchiveProtectionDomains && is_dumping_full_module_graph();
+ }
+ 
+ bool CDSConfig::is_loading_protection_domains() {
+   if (_is_security_manager_allowed) {
+     // For sanity, don't used any archived PDs. TODO: can this be relaxed?
+     return false;
+   }
+   return UseSharedSpaces && is_using_full_module_graph() && _is_loading_protection_domains;
+ }
+ 
+ bool CDSConfig::is_dumping_reflection_data() {
+   // reflection data use LambdaForm classes
+   return ArchiveReflectionData && is_dumping_invokedynamic();
+ }
+ 
  // When we are dumping aot-linked classes and we are able to write archived heap objects, we automatically
  // enable the archiving of MethodHandles. This will in turn enable the archiving of MethodTypes and hidden
  // classes that are used in the implementation of MethodHandles.
  // Archived MethodHandles are required for higher-level optimizations such as AOT resolution of invokedynamic
  // and dynamic proxies.
< prev index next >