8264872: Dependencies: Migrate to PerfData counters

Reviewed-by: kvn, neliasso
This commit is contained in:
Vladimir Ivanov 2021-04-09 22:18:56 +00:00
parent 07c8ff47d2
commit 76bd313d80
4 changed files with 84 additions and 60 deletions

View File

@ -41,6 +41,7 @@
#include "runtime/handles.hpp" #include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.inline.hpp" #include "runtime/jniHandles.inline.hpp"
#include "runtime/perfData.hpp"
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/vmThread.hpp" #include "runtime/vmThread.hpp"
#include "utilities/copy.hpp" #include "utilities/copy.hpp"
@ -951,7 +952,7 @@ bool DependencySignature::equals(DependencySignature const& s1, DependencySignat
return true; return true;
} }
/// Checking dependencies: /// Checking dependencies
// This hierarchy walker inspects subtypes of a given type, // This hierarchy walker inspects subtypes of a given type,
// trying to find a "bad" class which breaks a dependency. // trying to find a "bad" class which breaks a dependency.
@ -1145,6 +1146,24 @@ class ClassHierarchyWalker {
return false; // not in list return false; // not in list
} }
class CountingClassHierarchyIterator : public ClassHierarchyIterator {
private:
jlong _nof_steps;
public:
CountingClassHierarchyIterator(InstanceKlass* root) : ClassHierarchyIterator(root), _nof_steps(0) {}
void next() {
_nof_steps++;
ClassHierarchyIterator::next();
}
~CountingClassHierarchyIterator() {
if (UsePerfData) {
_perf_find_witness_anywhere_steps_count->inc(_nof_steps);
}
}
};
private: private:
// the actual search method: // the actual search method:
Klass* find_witness_anywhere(InstanceKlass* context_type, Klass* find_witness_anywhere(InstanceKlass* context_type,
@ -1179,53 +1198,32 @@ class ClassHierarchyWalker {
return find_witness_anywhere(context_type, !participants_hide_witnesses); return find_witness_anywhere(context_type, !participants_hide_witnesses);
} }
} }
private:
static PerfCounter* _perf_find_witness_anywhere_calls_count;
static PerfCounter* _perf_find_witness_anywhere_steps_count;
static PerfCounter* _perf_find_witness_in_calls_count;
public:
static void init();
static void print_statistics();
}; };
#ifndef PRODUCT PerfCounter* ClassHierarchyWalker::_perf_find_witness_anywhere_calls_count = NULL;
static int deps_find_witness_calls = 0; PerfCounter* ClassHierarchyWalker::_perf_find_witness_anywhere_steps_count = NULL;
static int deps_find_witness_steps = 0; PerfCounter* ClassHierarchyWalker::_perf_find_witness_in_calls_count = NULL;
static int deps_find_witness_recursions = 0;
static int deps_find_witness_singles = 0; void ClassHierarchyWalker::init() {
static int deps_find_witness_print = 0; // set to -1 to force a final print if (UsePerfData) {
static bool count_find_witness_calls() { EXCEPTION_MARK;
if (TraceDependencies || LogCompilation) { _perf_find_witness_anywhere_calls_count =
int pcount = deps_find_witness_print + 1; PerfDataManager::create_counter(SUN_CI, "findWitnessAnywhere", PerfData::U_Events, CHECK);
bool final_stats = (pcount == 0); _perf_find_witness_anywhere_steps_count =
bool initial_call = (pcount == 1); PerfDataManager::create_counter(SUN_CI, "findWitnessAnywhereSteps", PerfData::U_Events, CHECK);
bool occasional_print = ((pcount & ((1<<10) - 1)) == 0); _perf_find_witness_in_calls_count =
if (pcount < 0) pcount = 1; // crude overflow protection PerfDataManager::create_counter(SUN_CI, "findWitnessIn", PerfData::U_Events, CHECK);
deps_find_witness_print = pcount;
if (TraceDependencies && VerifyDependencies && initial_call) {
warning("TraceDependencies results may be inflated by VerifyDependencies");
}
if (occasional_print || final_stats) {
// Every now and then dump a little info about dependency searching.
if (xtty != NULL) {
ttyLocker ttyl;
xtty->elem("deps_find_witness calls='%d' steps='%d' recursions='%d' singles='%d'",
deps_find_witness_calls,
deps_find_witness_steps,
deps_find_witness_recursions,
deps_find_witness_singles);
}
if (final_stats || (TraceDependencies && WizardMode)) {
ttyLocker ttyl;
tty->print_cr("Dependency check (find_witness) "
"calls=%d, steps=%d (avg=%.1f), recursions=%d, singles=%d",
deps_find_witness_calls,
deps_find_witness_steps,
(double)deps_find_witness_steps / deps_find_witness_calls,
deps_find_witness_recursions,
deps_find_witness_singles);
}
}
return true;
} }
return false;
} }
#else
#define count_find_witness_calls() (0)
#endif //PRODUCT
#ifdef ASSERT #ifdef ASSERT
// Assert that m is inherited into ctxk, without intervening overrides. // Assert that m is inherited into ctxk, without intervening overrides.
@ -1291,8 +1289,9 @@ Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
assert(changes.involves_context(context_type), "irrelevant dependency"); assert(changes.involves_context(context_type), "irrelevant dependency");
Klass* new_type = changes.new_type(); Klass* new_type = changes.new_type();
(void)count_find_witness_calls(); if (UsePerfData) {
NOT_PRODUCT(deps_find_witness_singles++); _perf_find_witness_in_calls_count->inc();
}
// Current thread must be in VM (not native mode, as in CI): // Current thread must be in VM (not native mode, as in CI):
assert(must_be_in_vm(), "raw oops here"); assert(must_be_in_vm(), "raw oops here");
@ -1332,12 +1331,11 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(InstanceKlass* context_type,
// Must not move the class hierarchy during this check: // Must not move the class hierarchy during this check:
assert_locked_or_safepoint(Compile_lock); assert_locked_or_safepoint(Compile_lock);
bool do_counts = count_find_witness_calls(); if (UsePerfData) {
_perf_find_witness_anywhere_calls_count->inc();
}
// Check the root of the sub-hierarchy first. // Check the root of the sub-hierarchy first.
if (do_counts) {
NOT_PRODUCT(deps_find_witness_calls++);
}
// (Note: Interfaces do not have subclasses.) // (Note: Interfaces do not have subclasses.)
// If it is an interface, search its direct implementors. // If it is an interface, search its direct implementors.
@ -1362,11 +1360,9 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(InstanceKlass* context_type,
assert(!context_type->is_interface(), "not allowed"); assert(!context_type->is_interface(), "not allowed");
for (ClassHierarchyIterator iter(context_type); !iter.done(); iter.next()) { for (CountingClassHierarchyIterator iter(context_type); !iter.done(); iter.next()) {
Klass* sub = iter.klass(); Klass* sub = iter.klass();
if (do_counts) { NOT_PRODUCT(deps_find_witness_steps++); }
// Do not report participant types. // Do not report participant types.
if (is_participant(sub)) { if (is_participant(sub)) {
// Walk beneath a participant only when it doesn't hide witnesses. // Walk beneath a participant only when it doesn't hide witnesses.
@ -1779,15 +1775,31 @@ bool KlassDepChange::involves_context(Klass* k) {
return is_contained; return is_contained;
} }
#ifndef PRODUCT
void Dependencies::print_statistics() { void Dependencies::print_statistics() {
if (deps_find_witness_print != 0) { ClassHierarchyWalker::print_statistics();
// Call one final time, to flush out the data. }
deps_find_witness_print = -1;
count_find_witness_calls(); void ClassHierarchyWalker::print_statistics() {
if (UsePerfData) {
jlong deps_find_witness_calls = _perf_find_witness_anywhere_calls_count->get_value();
jlong deps_find_witness_steps = _perf_find_witness_anywhere_steps_count->get_value();
jlong deps_find_witness_singles = _perf_find_witness_in_calls_count->get_value();
ttyLocker ttyl;
tty->print_cr("Dependency check (find_witness) "
"calls=" JLONG_FORMAT ", steps=" JLONG_FORMAT " (avg=%.1f), singles=" JLONG_FORMAT,
deps_find_witness_calls,
deps_find_witness_steps,
(double)deps_find_witness_steps / deps_find_witness_calls,
deps_find_witness_singles);
if (xtty != NULL) {
xtty->elem("deps_find_witness calls='" JLONG_FORMAT "' steps='" JLONG_FORMAT "' singles='" JLONG_FORMAT "'",
deps_find_witness_calls,
deps_find_witness_steps,
deps_find_witness_singles);
}
} }
} }
#endif
CallSiteDepChange::CallSiteDepChange(Handle call_site, Handle method_handle) : CallSiteDepChange::CallSiteDepChange(Handle call_site, Handle method_handle) :
_call_site(call_site), _call_site(call_site),
@ -1795,3 +1807,7 @@ CallSiteDepChange::CallSiteDepChange(Handle call_site, Handle method_handle) :
assert(_call_site()->is_a(vmClasses::CallSite_klass()), "must be"); assert(_call_site()->is_a(vmClasses::CallSite_klass()), "must be");
assert(_method_handle.is_null() || _method_handle()->is_a(vmClasses::MethodHandle_klass()), "must be"); assert(_method_handle.is_null() || _method_handle()->is_a(vmClasses::MethodHandle_klass()), "must be");
} }
void dependencies_init() {
ClassHierarchyWalker::init();
}

View File

@ -614,7 +614,7 @@ class Dependencies: public ResourceObj {
}; };
friend class Dependencies::DepStream; friend class Dependencies::DepStream;
static void print_statistics() PRODUCT_RETURN; static void print_statistics();
}; };

View File

@ -3967,6 +3967,12 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
no_shared_spaces("CDS Disabled"); no_shared_spaces("CDS Disabled");
#endif // INCLUDE_CDS #endif // INCLUDE_CDS
if (TraceDependencies && VerifyDependencies) {
if (!FLAG_IS_DEFAULT(TraceDependencies)) {
warning("TraceDependencies results may be inflated by VerifyDependencies");
}
}
apply_debugger_ergo(); apply_debugger_ergo();
return JNI_OK; return JNI_OK;

View File

@ -85,6 +85,7 @@ void InlineCacheBuffer_init();
void compilerOracle_init(); void compilerOracle_init();
bool compileBroker_init(); bool compileBroker_init();
void dependencyContext_init(); void dependencyContext_init();
void dependencies_init();
// Initialization after compiler initialization // Initialization after compiler initialization
bool universe_post_init(); // must happen after compiler_init bool universe_post_init(); // must happen after compiler_init
@ -143,6 +144,7 @@ jint init_globals() {
InlineCacheBuffer_init(); InlineCacheBuffer_init();
compilerOracle_init(); compilerOracle_init();
dependencyContext_init(); dependencyContext_init();
dependencies_init();
if (!compileBroker_init()) { if (!compileBroker_init()) {
return JNI_EINVAL; return JNI_EINVAL;