8282024: add EscapeAnalysis statistics under PrintOptoStatistics

Reviewed-by: xliu, kvn
This commit is contained in:
Ana Marsh 2022-06-01 20:19:42 +00:00 committed by Vladimir Kozlov
parent cdb476888a
commit 2f19144249
5 changed files with 112 additions and 2 deletions

View File

@ -254,6 +254,8 @@ void Compile::print_statistics() {
PhaseOutput::print_statistics();
PhasePeephole::print_statistics();
PhaseIdealLoop::print_statistics();
ConnectionGraph::print_statistics();
PhaseMacroExpand::print_statistics();
if (xtty != NULL) xtty->tail("statistics");
}
if (_intrinsic_hist_flags[as_int(vmIntrinsics::_none)] != 0) {

View File

@ -233,6 +233,7 @@ bool ConnectionGraph::compute_escape() {
if (non_escaped_allocs_worklist.length() == 0) {
_collecting = false;
NOT_PRODUCT(escape_state_statistics(java_objects_worklist);)
return false; // Nothing to do.
}
// Add final simple edges to graph.
@ -262,7 +263,10 @@ bool ConnectionGraph::compute_escape() {
// processing, calls to CI to resolve symbols (types, fields, methods)
// referenced in bytecode. During symbol resolution VM may throw
// an exception which CI cleans and converts to compilation failure.
if (C->failing()) return false;
if (C->failing()) {
NOT_PRODUCT(escape_state_statistics(java_objects_worklist);)
return false;
}
// 2. Finish Graph construction by propagating references to all
// java objects through graph.
@ -270,6 +274,7 @@ bool ConnectionGraph::compute_escape() {
java_objects_worklist, oop_fields_worklist)) {
// All objects escaped or hit time or iterations limits.
_collecting = false;
NOT_PRODUCT(escape_state_statistics(java_objects_worklist);)
return false;
}
@ -339,7 +344,10 @@ bool ConnectionGraph::compute_escape() {
// Now use the escape information to create unique types for
// scalar replaceable objects.
split_unique_types(alloc_worklist, arraycopy_worklist, mergemem_worklist);
if (C->failing()) return false;
if (C->failing()) {
NOT_PRODUCT(escape_state_statistics(java_objects_worklist);)
return false;
}
C->print_method(PHASE_AFTER_EA, 2);
#ifdef ASSERT
@ -375,6 +383,7 @@ bool ConnectionGraph::compute_escape() {
}
}
NOT_PRODUCT(escape_state_statistics(java_objects_worklist);)
return has_non_escaping_obj;
}
@ -3673,6 +3682,10 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
}
#ifndef PRODUCT
int ConnectionGraph::_no_escape_counter = 0;
int ConnectionGraph::_arg_escape_counter = 0;
int ConnectionGraph::_global_escape_counter = 0;
static const char *node_type_names[] = {
"UnknownType",
"JavaObject",
@ -3781,6 +3794,30 @@ void ConnectionGraph::dump(GrowableArray<PointsToNode*>& ptnodes_worklist) {
}
}
void ConnectionGraph::print_statistics() {
tty->print_cr("No escape = %d, Arg escape = %d, Global escape = %d", Atomic::load(&_no_escape_counter), Atomic::load(&_arg_escape_counter), Atomic::load(&_global_escape_counter));
}
void ConnectionGraph::escape_state_statistics(GrowableArray<JavaObjectNode*>& java_objects_worklist) {
if (!PrintOptoStatistics || (_invocation > 0)) { // Collect data only for the first invocation
return;
}
for (int next = 0; next < java_objects_worklist.length(); ++next) {
JavaObjectNode* ptn = java_objects_worklist.at(next);
if (ptn->ideal_node()->is_Allocate()) {
if (ptn->escape_state() == PointsToNode::NoEscape) {
Atomic::inc(&ConnectionGraph::_no_escape_counter);
} else if (ptn->escape_state() == PointsToNode::ArgEscape) {
Atomic::inc(&ConnectionGraph::_arg_escape_counter);
} else if (ptn->escape_state() == PointsToNode::GlobalEscape) {
Atomic::inc(&ConnectionGraph::_global_escape_counter);
} else {
assert(false, "Unexpected Escape State");
}
}
}
}
void ConnectionGraph::trace_es_update_helper(PointsToNode* ptn, PointsToNode::EscapeState es, bool fields, const char* reason) const {
if (_compile->directive()->TraceEscapeAnalysisOption) {
assert(ptn != nullptr, "should not be null");

View File

@ -636,7 +636,12 @@ public:
bool add_final_edges_unsafe_access(Node* n, uint opcode);
#ifndef PRODUCT
static int _no_escape_counter;
static int _arg_escape_counter;
static int _global_escape_counter;
void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
static void print_statistics();
void escape_state_statistics(GrowableArray<JavaObjectNode*>& java_objects_worklist);
#endif
};

View File

@ -160,6 +160,11 @@ CallNode* PhaseMacroExpand::make_slow_call(CallNode *oldcall, const TypeFunc* sl
void PhaseMacroExpand::eliminate_gc_barrier(Node* p2x) {
BarrierSetC2 *bs = BarrierSet::barrier_set()->barrier_set_c2();
bs->eliminate_gc_barrier(this, p2x);
#ifndef PRODUCT
if (PrintOptoStatistics) {
Atomic::inc(&PhaseMacroExpand::_GC_barriers_removed_counter);
}
#endif
}
// Search for a memory operation for the specified memory slice.
@ -2339,6 +2344,7 @@ void PhaseMacroExpand::expand_subtypecheck_node(SubTypeCheckNode *check) {
void PhaseMacroExpand::eliminate_macro_nodes() {
if (C->macro_count() == 0)
return;
NOT_PRODUCT(int membar_before = count_MemBar(C);)
// Before elimination may re-mark (change to Nested or NonEscObj)
// all associated (same box and obj) lock and unlock nodes.
@ -2364,6 +2370,11 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
DEBUG_ONLY(int old_macro_count = C->macro_count();)
if (n->is_AbstractLock()) {
success = eliminate_locking_node(n->as_AbstractLock());
#ifndef PRODUCT
if (success && PrintOptoStatistics) {
Atomic::inc(&PhaseMacroExpand::_monitor_objects_removed_counter);
}
#endif
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;
@ -2382,6 +2393,11 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
case Node::Class_Allocate:
case Node::Class_AllocateArray:
success = eliminate_allocate_node(n->as_Allocate());
#ifndef PRODUCT
if (success && PrintOptoStatistics) {
Atomic::inc(&PhaseMacroExpand::_objs_scalar_replaced_counter);
}
#endif
break;
case Node::Class_CallStaticJava:
success = eliminate_boxing_node(n->as_CallStaticJava());
@ -2411,6 +2427,12 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
progress = progress || success;
}
}
#ifndef PRODUCT
if (PrintOptoStatistics) {
int membar_after = count_MemBar(C);
Atomic::add(&PhaseMacroExpand::_memory_barriers_removed_counter, membar_before - membar_after);
}
#endif
}
//------------------------------expand_macro_nodes----------------------
@ -2599,3 +2621,38 @@ bool PhaseMacroExpand::expand_macro_nodes() {
_igvn.set_delay_transform(false);
return false;
}
#ifndef PRODUCT
int PhaseMacroExpand::_objs_scalar_replaced_counter = 0;
int PhaseMacroExpand::_monitor_objects_removed_counter = 0;
int PhaseMacroExpand::_GC_barriers_removed_counter = 0;
int PhaseMacroExpand::_memory_barriers_removed_counter = 0;
void PhaseMacroExpand::print_statistics() {
tty->print("Objects scalar replaced = %d, ", Atomic::load(&_objs_scalar_replaced_counter));
tty->print("Monitor objects removed = %d, ", Atomic::load(&_monitor_objects_removed_counter));
tty->print("GC barriers removed = %d, ", Atomic::load(&_GC_barriers_removed_counter));
tty->print_cr("Memory barriers removed = %d", Atomic::load(&_memory_barriers_removed_counter));
}
int PhaseMacroExpand::count_MemBar(Compile *C) {
if (!PrintOptoStatistics) {
return 0;
}
Unique_Node_List ideal_nodes;
int total = 0;
ideal_nodes.map(C->live_nodes(), NULL);
ideal_nodes.push(C->root());
for (uint next = 0; next < ideal_nodes.size(); ++next) {
Node* n = ideal_nodes.at(next);
if (n->is_MemBar()) {
total++;
}
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* m = n->fast_out(i);
ideal_nodes.push(m);
}
}
return total;
}
#endif

View File

@ -208,6 +208,15 @@ public:
PhaseIterGVN &igvn() const { return _igvn; }
#ifndef PRODUCT
static int _objs_scalar_replaced_counter;
static int _monitor_objects_removed_counter;
static int _GC_barriers_removed_counter;
static int _memory_barriers_removed_counter;
static void print_statistics();
static int count_MemBar(Compile *C);
#endif
// Members accessed from BarrierSetC2
void replace_node(Node* source, Node* target) { _igvn.replace_node(source, target); }
Node* intcon(jint con) const { return _igvn.intcon(con); }