8324241: Always record evol_method deps to avoid excessive method flushing

Reviewed-by: eastigeevich, phh, coleenp, dlong, shade
This commit is contained in:
Volker Simonis 2024-01-26 13:11:58 +00:00
parent 885e9b76d6
commit 62b3293df0
4 changed files with 31 additions and 11 deletions

View File

@ -149,7 +149,15 @@ class JvmtiExport : public AllStatic {
JVMTI_ONLY(_can_access_local_variables = (on != 0);)
}
inline static void set_can_hotswap_or_post_breakpoint(bool on) {
JVMTI_ONLY(_can_hotswap_or_post_breakpoint = (on != 0);)
#if INCLUDE_JVMTI
// Check that _can_hotswap_or_post_breakpoint is not reset once it
// was set to true. When _can_hotswap_or_post_breakpoint is set to true
// _all_dependencies_are_recorded is also set to true and never
// reset so we have to ensure that evol dependencies are always
// recorded from that point on.
assert(!_can_hotswap_or_post_breakpoint || on, "sanity check");
_can_hotswap_or_post_breakpoint = (on != 0);
#endif
}
inline static void set_can_walk_any_space(bool on) {
JVMTI_ONLY(_can_walk_any_space = (on != 0);)

View File

@ -4060,21 +4060,22 @@ void VM_RedefineClasses::transfer_old_native_function_registrations(InstanceKlas
// Deoptimize all compiled code that depends on the classes redefined.
//
// If the can_redefine_classes capability is obtained in the onload
// phase then the compiler has recorded all dependencies from startup.
// In that case we need only deoptimize and throw away all compiled code
// that depends on the class.
// phase or 'AlwaysRecordEvolDependencies' is true, then the compiler has
// recorded all dependencies from startup. In that case we need only
// deoptimize and throw away all compiled code that depends on the class.
//
// If can_redefine_classes is obtained sometime after the onload
// phase then the dependency information may be incomplete. In that case
// the first call to RedefineClasses causes all compiled code to be
// thrown away. As can_redefine_classes has been obtained then
// all future compilations will record dependencies so second and
// subsequent calls to RedefineClasses need only throw away code
// that depends on the class.
// If can_redefine_classes is obtained sometime after the onload phase
// (and 'AlwaysRecordEvolDependencies' is false) then the dependency
// information may be incomplete. In that case the first call to
// RedefineClasses causes all compiled code to be thrown away. As
// can_redefine_classes has been obtained then all future compilations will
// record dependencies so second and subsequent calls to RedefineClasses
// need only throw away code that depends on the class.
//
void VM_RedefineClasses::flush_dependent_code() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
assert(JvmtiExport::all_dependencies_are_recorded() || !AlwaysRecordEvolDependencies, "sanity check");
DeoptimizationScope deopt_scope;

View File

@ -2009,6 +2009,11 @@ const int ObjectAlignmentInBytes = 8;
\
product(bool, ProfileExceptionHandlers, true, \
"Profile exception handlers") \
\
product(bool, AlwaysRecordEvolDependencies, true, EXPERIMENTAL, \
"Unconditionally record nmethod dependencies on class " \
"rewriting/transformation independently of the JVMTI " \
"can_{retransform/redefine}_classes capabilities.") \
// end of RUNTIME_FLAGS

View File

@ -115,6 +115,12 @@ void vm_init_globals() {
jint init_globals() {
management_init();
JvmtiExport::initialize_oop_storage();
#if INCLUDE_JVMTI
if (AlwaysRecordEvolDependencies) {
JvmtiExport::set_can_hotswap_or_post_breakpoint(true);
JvmtiExport::set_all_dependencies_are_recorded(true);
}
#endif
bytecodes_init();
classLoader_init1();
compilationPolicy_init();