8261447: MethodInvocationCounters frequently run into overflow
Reviewed-by: thartmann, mdoerr, kvn, iveresov
This commit is contained in:
parent
75aa15467e
commit
268d9b7982
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -70,7 +70,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
#if (!defined(PRODUCT) && defined(COMPILER2))
|
||||
if (CountCompiledCalls) {
|
||||
__ lea(r16, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
||||
__ incrementw(Address(r16));
|
||||
__ increment(Address(r16));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -145,6 +145,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Count unused bytes in instruction sequences of variable size.
|
||||
// We add them to the computed buffer size in order to avoid
|
||||
// overflow in subsequently generated stubs.
|
||||
@ -159,7 +160,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
#if (!defined(PRODUCT) && defined(COMPILER2))
|
||||
if (CountCompiledCalls) {
|
||||
__ lea(r10, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
||||
__ incrementw(Address(r10));
|
||||
__ increment(Address(r10));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -73,9 +73,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
slop_delta = load_const_maxLen - (__ pc() - start_pc);
|
||||
slop_bytes += slop_delta;
|
||||
assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta);
|
||||
__ lwz(R12_scratch2, offs, R11_scratch1);
|
||||
__ ld(R12_scratch2, offs, R11_scratch1);
|
||||
__ addi(R12_scratch2, R12_scratch2, 1);
|
||||
__ stw(R12_scratch2, offs, R11_scratch1);
|
||||
__ std(R12_scratch2, offs, R11_scratch1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -141,6 +141,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Count unused bytes in instruction sequences of variable size.
|
||||
// We add them to the computed buffer size in order to avoid
|
||||
// overflow in subsequently generated stubs.
|
||||
@ -160,9 +161,9 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
slop_delta = load_const_maxLen - (__ pc() - start_pc);
|
||||
slop_bytes += slop_delta;
|
||||
assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta);
|
||||
__ lwz(R12_scratch2, offs, R11_scratch1);
|
||||
__ ld(R12_scratch2, offs, R11_scratch1);
|
||||
__ addi(R12_scratch2, R12_scratch2, 1);
|
||||
__ stw(R12_scratch2, offs, R11_scratch1);
|
||||
__ std(R12_scratch2, offs, R11_scratch1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2021 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,7 +75,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
// Abuse Z_method as scratch register for generic emitter.
|
||||
// It is loaded further down anyway before it is first used.
|
||||
// No dynamic code size variance here, increment is 1, always.
|
||||
__ add2mem_32(Address(Z_R1_scratch), 1, Z_method);
|
||||
__ add2mem_64(Address(Z_R1_scratch), 1, Z_method);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -158,6 +158,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Count unused bytes in instruction sequences of variable size.
|
||||
// We add them to the computed buffer size in order to avoid
|
||||
// overflow in subsequently generated stubs.
|
||||
@ -179,7 +180,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
// Abuse Z_method as scratch register for generic emitter.
|
||||
// It is loaded further down anyway before it is first used.
|
||||
// No dynamic code size variance here, increment is 1, always.
|
||||
__ add2mem_32(Address(Z_R1_scratch), 1, Z_method);
|
||||
__ add2mem_64(Address(Z_R1_scratch), 1, Z_method);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -70,7 +70,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
|
||||
#if (!defined(PRODUCT) && defined(COMPILER2))
|
||||
if (CountCompiledCalls) {
|
||||
__ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
||||
__ incrementq(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -148,6 +148,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Count unused bytes in instruction sequences of variable size.
|
||||
// We add them to the computed buffer size in order to avoid
|
||||
// overflow in subsequently generated stubs.
|
||||
@ -163,7 +164,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
|
||||
#if (!defined(PRODUCT) && defined(COMPILER2))
|
||||
if (CountCompiledCalls) {
|
||||
__ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
||||
__ incrementq(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
|
@ -493,6 +493,7 @@ bool Method::was_executed_more_than(int n) {
|
||||
}
|
||||
|
||||
void Method::print_invocation_count() {
|
||||
//---< compose+print method return type, klass, name, and signature >---
|
||||
if (is_static()) tty->print("static ");
|
||||
if (is_final()) tty->print("final ");
|
||||
if (is_synchronized()) tty->print("synchronized ");
|
||||
@ -507,12 +508,22 @@ void Method::print_invocation_count() {
|
||||
}
|
||||
tty->cr();
|
||||
|
||||
tty->print_cr (" interpreter_invocation_count: %8d ", interpreter_invocation_count());
|
||||
tty->print_cr (" invocation_counter: %8d ", invocation_count());
|
||||
tty->print_cr (" backedge_counter: %8d ", backedge_count());
|
||||
// Counting based on signed int counters tends to overflow with
|
||||
// longer-running workloads on fast machines. The counters under
|
||||
// consideration here, however, are limited in range by counting
|
||||
// logic. See InvocationCounter:count_limit for example.
|
||||
// No "overflow precautions" need to be implemented here.
|
||||
tty->print_cr (" interpreter_invocation_count: " INT32_FORMAT_W(11), interpreter_invocation_count());
|
||||
tty->print_cr (" invocation_counter: " INT32_FORMAT_W(11), invocation_count());
|
||||
tty->print_cr (" backedge_counter: " INT32_FORMAT_W(11), backedge_count());
|
||||
|
||||
if (method_data() != NULL) {
|
||||
tty->print_cr (" decompile_count: " UINT32_FORMAT_W(11), method_data()->decompile_count());
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (CountCompiledCalls) {
|
||||
tty->print_cr (" compiled_invocation_count: %8d ", compiled_invocation_count());
|
||||
tty->print_cr (" compiled_invocation_count: " INT64_FORMAT_W(11), compiled_invocation_count());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ class Method : public Metadata {
|
||||
JFR_ONLY(DEFINE_TRACE_FLAG;)
|
||||
|
||||
#ifndef PRODUCT
|
||||
int _compiled_invocation_count; // Number of nmethod invocations so far (for perf. debugging)
|
||||
int64_t _compiled_invocation_count;
|
||||
#endif
|
||||
// Entry point for calling both from and to the interpreter.
|
||||
address _i2i_entry; // All-args-on-stack calling convention
|
||||
@ -436,11 +436,11 @@ class Method : public Metadata {
|
||||
int interpreter_invocation_count() { return invocation_count(); }
|
||||
|
||||
#ifndef PRODUCT
|
||||
int compiled_invocation_count() const { return _compiled_invocation_count; }
|
||||
void set_compiled_invocation_count(int count) { _compiled_invocation_count = count; }
|
||||
int64_t compiled_invocation_count() const { return _compiled_invocation_count;}
|
||||
void set_compiled_invocation_count(int count) { _compiled_invocation_count = (int64_t)count; }
|
||||
#else
|
||||
// for PrintMethodData in a product build
|
||||
int compiled_invocation_count() const { return 0; }
|
||||
int64_t compiled_invocation_count() const { return 0; }
|
||||
#endif // not PRODUCT
|
||||
|
||||
// Clear (non-shared space) pointers which could not be relevant
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -2000,9 +2000,9 @@ void GraphKit::increment_counter(address counter_addr) {
|
||||
void GraphKit::increment_counter(Node* counter_addr) {
|
||||
int adr_type = Compile::AliasIdxRaw;
|
||||
Node* ctrl = control();
|
||||
Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
|
||||
Node* incr = _gvn.transform(new AddINode(cnt, _gvn.intcon(1)));
|
||||
store_to_memory(ctrl, counter_addr, incr, T_INT, adr_type, MemNode::unordered);
|
||||
Node* cnt = make_load(ctrl, counter_addr, TypeLong::LONG, T_LONG, adr_type, MemNode::unordered);
|
||||
Node* incr = _gvn.transform(new AddLNode(cnt, _gvn.longcon(1)));
|
||||
store_to_memory(ctrl, counter_addr, incr, T_LONG, adr_type, MemNode::unordered);
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,9 +97,11 @@
|
||||
GrowableArray<Method*>* collected_profiled_methods;
|
||||
|
||||
int compare_methods(Method** a, Method** b) {
|
||||
// %%% there can be 32-bit overflow here
|
||||
return ((*b)->invocation_count() + (*b)->compiled_invocation_count())
|
||||
- ((*a)->invocation_count() + (*a)->compiled_invocation_count());
|
||||
// compiled_invocation_count() returns int64_t, forcing the entire expression
|
||||
// to be evaluated as int64_t. Overflow is not an issue.
|
||||
int64_t diff = (((*b)->invocation_count() + (*b)->compiled_invocation_count())
|
||||
- ((*a)->invocation_count() + (*a)->compiled_invocation_count()));
|
||||
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void collect_profiled_methods(Method* m) {
|
||||
@ -151,14 +153,15 @@ void print_method_profiling_data() {
|
||||
GrowableArray<Method*>* collected_invoked_methods;
|
||||
|
||||
void collect_invoked_methods(Method* m) {
|
||||
if (m->invocation_count() + m->compiled_invocation_count() >= 1 ) {
|
||||
if (m->invocation_count() + m->compiled_invocation_count() >= 1) {
|
||||
collected_invoked_methods->push(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Invocation count accumulators should be unsigned long to shift the
|
||||
// overflow border. Longer-running workloads tend to create invocation
|
||||
// counts which already overflow 32-bit counters for individual methods.
|
||||
void print_method_invocation_histogram() {
|
||||
ResourceMark rm;
|
||||
collected_invoked_methods = new GrowableArray<Method*>(1024);
|
||||
@ -169,31 +172,45 @@ void print_method_invocation_histogram() {
|
||||
tty->print_cr("Histogram Over Method Invocation Counters (cutoff = " INTX_FORMAT "):", MethodHistogramCutoff);
|
||||
tty->cr();
|
||||
tty->print_cr("____Count_(I+C)____Method________________________Module_________________");
|
||||
unsigned total = 0, int_total = 0, comp_total = 0, static_total = 0, final_total = 0,
|
||||
synch_total = 0, nativ_total = 0, acces_total = 0;
|
||||
uint64_t total = 0,
|
||||
int_total = 0,
|
||||
comp_total = 0,
|
||||
special_total= 0,
|
||||
static_total = 0,
|
||||
final_total = 0,
|
||||
synch_total = 0,
|
||||
native_total = 0,
|
||||
access_total = 0;
|
||||
for (int index = 0; index < collected_invoked_methods->length(); index++) {
|
||||
// Counter values returned from getter methods are signed int.
|
||||
// To shift the overflow border by a factor of two, we interpret
|
||||
// them here as unsigned long. A counter can't be negative anyway.
|
||||
Method* m = collected_invoked_methods->at(index);
|
||||
int c = m->invocation_count() + m->compiled_invocation_count();
|
||||
if (c >= MethodHistogramCutoff) m->print_invocation_count();
|
||||
int_total += m->invocation_count();
|
||||
comp_total += m->compiled_invocation_count();
|
||||
if (m->is_final()) final_total += c;
|
||||
if (m->is_static()) static_total += c;
|
||||
if (m->is_synchronized()) synch_total += c;
|
||||
if (m->is_native()) nativ_total += c;
|
||||
if (m->is_accessor()) acces_total += c;
|
||||
uint64_t iic = (uint64_t)m->invocation_count();
|
||||
uint64_t cic = (uint64_t)m->compiled_invocation_count();
|
||||
if ((iic + cic) >= (uint64_t)MethodHistogramCutoff) m->print_invocation_count();
|
||||
int_total += iic;
|
||||
comp_total += cic;
|
||||
if (m->is_final()) final_total += iic + cic;
|
||||
if (m->is_static()) static_total += iic + cic;
|
||||
if (m->is_synchronized()) synch_total += iic + cic;
|
||||
if (m->is_native()) native_total += iic + cic;
|
||||
if (m->is_accessor()) access_total += iic + cic;
|
||||
}
|
||||
tty->cr();
|
||||
total = int_total + comp_total;
|
||||
tty->print_cr("Invocations summary:");
|
||||
tty->print_cr("\t%9d (%4.1f%%) interpreted", int_total, 100.0 * int_total / total);
|
||||
tty->print_cr("\t%9d (%4.1f%%) compiled", comp_total, 100.0 * comp_total / total);
|
||||
tty->print_cr("\t%9d (100%%) total", total);
|
||||
tty->print_cr("\t%9d (%4.1f%%) synchronized", synch_total, 100.0 * synch_total / total);
|
||||
tty->print_cr("\t%9d (%4.1f%%) final", final_total, 100.0 * final_total / total);
|
||||
tty->print_cr("\t%9d (%4.1f%%) static", static_total, 100.0 * static_total / total);
|
||||
tty->print_cr("\t%9d (%4.1f%%) native", nativ_total, 100.0 * nativ_total / total);
|
||||
tty->print_cr("\t%9d (%4.1f%%) accessor", acces_total, 100.0 * acces_total / total);
|
||||
special_total = final_total + static_total +synch_total + native_total + access_total;
|
||||
tty->print_cr("Invocations summary for %d methods:", collected_invoked_methods->length());
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (100%%) total", total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- interpreted", int_total, 100.0 * int_total / total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- compiled", comp_total, 100.0 * comp_total / total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- special methods (interpreted and compiled)",
|
||||
special_total, 100.0 * special_total/ total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- synchronized",synch_total, 100.0 * synch_total / total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- final", final_total, 100.0 * final_total / total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- static", static_total, 100.0 * static_total / total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- native", native_total, 100.0 * native_total / total);
|
||||
tty->print_cr("\t" UINT64_FORMAT_W(12) " (%4.1f%%) |- accessor", access_total, 100.0 * access_total / total);
|
||||
tty->cr();
|
||||
SharedRuntime::print_call_statistics(comp_total);
|
||||
}
|
||||
|
@ -143,16 +143,16 @@ int SharedRuntime::_implicit_null_throws = 0;
|
||||
int SharedRuntime::_implicit_div0_throws = 0;
|
||||
int SharedRuntime::_throw_null_ctr = 0;
|
||||
|
||||
int SharedRuntime::_nof_normal_calls = 0;
|
||||
int SharedRuntime::_nof_optimized_calls = 0;
|
||||
int SharedRuntime::_nof_inlined_calls = 0;
|
||||
int SharedRuntime::_nof_megamorphic_calls = 0;
|
||||
int SharedRuntime::_nof_static_calls = 0;
|
||||
int SharedRuntime::_nof_inlined_static_calls = 0;
|
||||
int SharedRuntime::_nof_interface_calls = 0;
|
||||
int SharedRuntime::_nof_optimized_interface_calls = 0;
|
||||
int SharedRuntime::_nof_inlined_interface_calls = 0;
|
||||
int SharedRuntime::_nof_megamorphic_interface_calls = 0;
|
||||
int64_t SharedRuntime::_nof_normal_calls = 0;
|
||||
int64_t SharedRuntime::_nof_optimized_calls = 0;
|
||||
int64_t SharedRuntime::_nof_inlined_calls = 0;
|
||||
int64_t SharedRuntime::_nof_megamorphic_calls = 0;
|
||||
int64_t SharedRuntime::_nof_static_calls = 0;
|
||||
int64_t SharedRuntime::_nof_inlined_static_calls = 0;
|
||||
int64_t SharedRuntime::_nof_interface_calls = 0;
|
||||
int64_t SharedRuntime::_nof_optimized_interface_calls = 0;
|
||||
int64_t SharedRuntime::_nof_inlined_interface_calls = 0;
|
||||
int64_t SharedRuntime::_nof_megamorphic_interface_calls = 0;
|
||||
|
||||
int SharedRuntime::_new_instance_ctr=0;
|
||||
int SharedRuntime::_new_array_ctr=0;
|
||||
@ -2203,14 +2203,20 @@ inline double percent(int x, int y) {
|
||||
return 100.0 * x / MAX2(y, 1);
|
||||
}
|
||||
|
||||
inline double percent(int64_t x, int64_t y) {
|
||||
return 100.0 * x / MAX2(y, (int64_t)1);
|
||||
}
|
||||
|
||||
class MethodArityHistogram {
|
||||
public:
|
||||
enum { MAX_ARITY = 256 };
|
||||
private:
|
||||
static int _arity_histogram[MAX_ARITY]; // histogram of #args
|
||||
static int _size_histogram[MAX_ARITY]; // histogram of arg size in words
|
||||
static int _max_arity; // max. arity seen
|
||||
static int _max_size; // max. arg size seen
|
||||
static uint64_t _arity_histogram[MAX_ARITY]; // histogram of #args
|
||||
static uint64_t _size_histogram[MAX_ARITY]; // histogram of arg size in words
|
||||
static uint64_t _total_compiled_calls;
|
||||
static uint64_t _max_compiled_calls_per_method;
|
||||
static int _max_arity; // max. arity seen
|
||||
static int _max_size; // max. arg size seen
|
||||
|
||||
static void add_method_to_histogram(nmethod* nm) {
|
||||
Method* method = (nm == NULL) ? NULL : nm->method();
|
||||
@ -2220,7 +2226,9 @@ class MethodArityHistogram {
|
||||
int argsize = method->size_of_parameters();
|
||||
arity = MIN2(arity, MAX_ARITY-1);
|
||||
argsize = MIN2(argsize, MAX_ARITY-1);
|
||||
int count = method->compiled_invocation_count();
|
||||
uint64_t count = (uint64_t)method->compiled_invocation_count();
|
||||
_max_compiled_calls_per_method = count > _max_compiled_calls_per_method ? count : _max_compiled_calls_per_method;
|
||||
_total_compiled_calls += count;
|
||||
_arity_histogram[arity] += count;
|
||||
_size_histogram[argsize] += count;
|
||||
_max_arity = MAX2(_max_arity, arity);
|
||||
@ -2228,27 +2236,31 @@ class MethodArityHistogram {
|
||||
}
|
||||
}
|
||||
|
||||
void print_histogram_helper(int n, int* histo, const char* name) {
|
||||
const int N = MIN2(5, n);
|
||||
tty->print_cr("\nHistogram of call arity (incl. rcvr, calls to compiled methods only):");
|
||||
void print_histogram_helper(int n, uint64_t* histo, const char* name) {
|
||||
const int N = MIN2(9, n);
|
||||
double sum = 0;
|
||||
double weighted_sum = 0;
|
||||
int i;
|
||||
for (i = 0; i <= n; i++) { sum += histo[i]; weighted_sum += i*histo[i]; }
|
||||
double rest = sum;
|
||||
double percent = sum / 100;
|
||||
for (i = 0; i <= N; i++) {
|
||||
rest -= histo[i];
|
||||
tty->print_cr("%4d: %7d (%5.1f%%)", i, histo[i], histo[i] / percent);
|
||||
for (int i = 0; i <= n; i++) { sum += histo[i]; weighted_sum += i*histo[i]; }
|
||||
if (sum >= 1.0) { // prevent divide by zero or divide overflow
|
||||
double rest = sum;
|
||||
double percent = sum / 100;
|
||||
for (int i = 0; i <= N; i++) {
|
||||
rest -= histo[i];
|
||||
tty->print_cr("%4d: " UINT64_FORMAT_W(12) " (%5.1f%%)", i, histo[i], histo[i] / percent);
|
||||
}
|
||||
tty->print_cr("rest: " INT64_FORMAT_W(12) " (%5.1f%%)", (int64_t)rest, rest / percent);
|
||||
tty->print_cr("(avg. %s = %3.1f, max = %d)", name, weighted_sum / sum, n);
|
||||
tty->print_cr("(total # of compiled calls = " INT64_FORMAT_W(14) ")", _total_compiled_calls);
|
||||
tty->print_cr("(max # of compiled calls = " INT64_FORMAT_W(14) ")", _max_compiled_calls_per_method);
|
||||
} else {
|
||||
tty->print_cr("Histogram generation failed for %s. n = %d, sum = %7.5f", name, n, sum);
|
||||
}
|
||||
tty->print_cr("rest: %7d (%5.1f%%))", (int)rest, rest / percent);
|
||||
tty->print_cr("(avg. %s = %3.1f, max = %d)", name, weighted_sum / sum, n);
|
||||
}
|
||||
|
||||
void print_histogram() {
|
||||
tty->print_cr("\nHistogram of call arity (incl. rcvr, calls to compiled methods only):");
|
||||
print_histogram_helper(_max_arity, _arity_histogram, "arity");
|
||||
tty->print_cr("\nSame for parameter size (in words):");
|
||||
tty->print_cr("\nHistogram of parameter block size (in words, incl. rcvr):");
|
||||
print_histogram_helper(_max_size, _size_histogram, "size");
|
||||
tty->cr();
|
||||
}
|
||||
@ -2260,35 +2272,39 @@ class MethodArityHistogram {
|
||||
// Take the CodeCache_lock to protect against changes in the CodeHeap structure
|
||||
MutexLocker mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
_max_arity = _max_size = 0;
|
||||
_total_compiled_calls = 0;
|
||||
_max_compiled_calls_per_method = 0;
|
||||
for (int i = 0; i < MAX_ARITY; i++) _arity_histogram[i] = _size_histogram[i] = 0;
|
||||
CodeCache::nmethods_do(add_method_to_histogram);
|
||||
print_histogram();
|
||||
}
|
||||
};
|
||||
|
||||
int MethodArityHistogram::_arity_histogram[MethodArityHistogram::MAX_ARITY];
|
||||
int MethodArityHistogram::_size_histogram[MethodArityHistogram::MAX_ARITY];
|
||||
uint64_t MethodArityHistogram::_arity_histogram[MethodArityHistogram::MAX_ARITY];
|
||||
uint64_t MethodArityHistogram::_size_histogram[MethodArityHistogram::MAX_ARITY];
|
||||
uint64_t MethodArityHistogram::_total_compiled_calls;
|
||||
uint64_t MethodArityHistogram::_max_compiled_calls_per_method;
|
||||
int MethodArityHistogram::_max_arity;
|
||||
int MethodArityHistogram::_max_size;
|
||||
|
||||
void SharedRuntime::print_call_statistics(int comp_total) {
|
||||
void SharedRuntime::print_call_statistics(uint64_t comp_total) {
|
||||
tty->print_cr("Calls from compiled code:");
|
||||
int total = _nof_normal_calls + _nof_interface_calls + _nof_static_calls;
|
||||
int mono_c = _nof_normal_calls - _nof_optimized_calls - _nof_megamorphic_calls;
|
||||
int mono_i = _nof_interface_calls - _nof_optimized_interface_calls - _nof_megamorphic_interface_calls;
|
||||
tty->print_cr("\t%9d (%4.1f%%) total non-inlined ", total, percent(total, total));
|
||||
tty->print_cr("\t%9d (%4.1f%%) virtual calls ", _nof_normal_calls, percent(_nof_normal_calls, total));
|
||||
tty->print_cr("\t %9d (%3.0f%%) inlined ", _nof_inlined_calls, percent(_nof_inlined_calls, _nof_normal_calls));
|
||||
tty->print_cr("\t %9d (%3.0f%%) optimized ", _nof_optimized_calls, percent(_nof_optimized_calls, _nof_normal_calls));
|
||||
tty->print_cr("\t %9d (%3.0f%%) monomorphic ", mono_c, percent(mono_c, _nof_normal_calls));
|
||||
tty->print_cr("\t %9d (%3.0f%%) megamorphic ", _nof_megamorphic_calls, percent(_nof_megamorphic_calls, _nof_normal_calls));
|
||||
tty->print_cr("\t%9d (%4.1f%%) interface calls ", _nof_interface_calls, percent(_nof_interface_calls, total));
|
||||
tty->print_cr("\t %9d (%3.0f%%) inlined ", _nof_inlined_interface_calls, percent(_nof_inlined_interface_calls, _nof_interface_calls));
|
||||
tty->print_cr("\t %9d (%3.0f%%) optimized ", _nof_optimized_interface_calls, percent(_nof_optimized_interface_calls, _nof_interface_calls));
|
||||
tty->print_cr("\t %9d (%3.0f%%) monomorphic ", mono_i, percent(mono_i, _nof_interface_calls));
|
||||
tty->print_cr("\t %9d (%3.0f%%) megamorphic ", _nof_megamorphic_interface_calls, percent(_nof_megamorphic_interface_calls, _nof_interface_calls));
|
||||
tty->print_cr("\t%9d (%4.1f%%) static/special calls", _nof_static_calls, percent(_nof_static_calls, total));
|
||||
tty->print_cr("\t %9d (%3.0f%%) inlined ", _nof_inlined_static_calls, percent(_nof_inlined_static_calls, _nof_static_calls));
|
||||
int64_t total = _nof_normal_calls + _nof_interface_calls + _nof_static_calls;
|
||||
int64_t mono_c = _nof_normal_calls - _nof_optimized_calls - _nof_megamorphic_calls;
|
||||
int64_t mono_i = _nof_interface_calls - _nof_optimized_interface_calls - _nof_megamorphic_interface_calls;
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (100%%) total non-inlined ", total);
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.1f%%) |- virtual calls ", _nof_normal_calls, percent(_nof_normal_calls, total));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- inlined ", _nof_inlined_calls, percent(_nof_inlined_calls, _nof_normal_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- optimized ", _nof_optimized_calls, percent(_nof_optimized_calls, _nof_normal_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- monomorphic ", mono_c, percent(mono_c, _nof_normal_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- megamorphic ", _nof_megamorphic_calls, percent(_nof_megamorphic_calls, _nof_normal_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.1f%%) |- interface calls ", _nof_interface_calls, percent(_nof_interface_calls, total));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- inlined ", _nof_inlined_interface_calls, percent(_nof_inlined_interface_calls, _nof_interface_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- optimized ", _nof_optimized_interface_calls, percent(_nof_optimized_interface_calls, _nof_interface_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- monomorphic ", mono_i, percent(mono_i, _nof_interface_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- megamorphic ", _nof_megamorphic_interface_calls, percent(_nof_megamorphic_interface_calls, _nof_interface_calls));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.1f%%) |- static/special calls", _nof_static_calls, percent(_nof_static_calls, total));
|
||||
tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- inlined ", _nof_inlined_static_calls, percent(_nof_inlined_static_calls, _nof_static_calls));
|
||||
tty->cr();
|
||||
tty->print_cr("Note 1: counter updates are not MT-safe.");
|
||||
tty->print_cr("Note 2: %% in major categories are relative to total non-inlined calls;");
|
||||
|
@ -78,7 +78,7 @@ class SharedRuntime: AllStatic {
|
||||
|
||||
#ifndef PRODUCT
|
||||
// Counters
|
||||
static int _nof_megamorphic_calls; // total # of megamorphic calls (through vtable)
|
||||
static int64_t _nof_megamorphic_calls; // total # of megamorphic calls (through vtable)
|
||||
#endif // !PRODUCT
|
||||
|
||||
private:
|
||||
@ -567,16 +567,16 @@ class SharedRuntime: AllStatic {
|
||||
|
||||
// Statistics code
|
||||
// stats for "normal" compiled calls (non-interface)
|
||||
static int _nof_normal_calls; // total # of calls
|
||||
static int _nof_optimized_calls; // total # of statically-bound calls
|
||||
static int _nof_inlined_calls; // total # of inlined normal calls
|
||||
static int _nof_static_calls; // total # of calls to static methods or super methods (invokespecial)
|
||||
static int _nof_inlined_static_calls; // total # of inlined static calls
|
||||
static int64_t _nof_normal_calls; // total # of calls
|
||||
static int64_t _nof_optimized_calls; // total # of statically-bound calls
|
||||
static int64_t _nof_inlined_calls; // total # of inlined normal calls
|
||||
static int64_t _nof_static_calls; // total # of calls to static methods or super methods (invokespecial)
|
||||
static int64_t _nof_inlined_static_calls; // total # of inlined static calls
|
||||
// stats for compiled interface calls
|
||||
static int _nof_interface_calls; // total # of compiled calls
|
||||
static int _nof_optimized_interface_calls; // total # of statically-bound interface calls
|
||||
static int _nof_inlined_interface_calls; // total # of inlined interface calls
|
||||
static int _nof_megamorphic_interface_calls;// total # of megamorphic interface calls
|
||||
static int64_t _nof_interface_calls; // total # of compiled calls
|
||||
static int64_t _nof_optimized_interface_calls; // total # of statically-bound interface calls
|
||||
static int64_t _nof_inlined_interface_calls; // total # of inlined interface calls
|
||||
static int64_t _nof_megamorphic_interface_calls;// total # of megamorphic interface calls
|
||||
|
||||
public: // for compiler
|
||||
static address nof_normal_calls_addr() { return (address)&_nof_normal_calls; }
|
||||
@ -588,7 +588,7 @@ class SharedRuntime: AllStatic {
|
||||
static address nof_optimized_interface_calls_addr() { return (address)&_nof_optimized_interface_calls; }
|
||||
static address nof_inlined_interface_calls_addr() { return (address)&_nof_inlined_interface_calls; }
|
||||
static address nof_megamorphic_interface_calls_addr() { return (address)&_nof_megamorphic_interface_calls; }
|
||||
static void print_call_statistics(int comp_total);
|
||||
static void print_call_statistics(uint64_t comp_total);
|
||||
static void print_statistics();
|
||||
static void print_ic_miss_histogram();
|
||||
|
||||
|
@ -307,7 +307,6 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
nonstatic_field(Method, _vtable_index, int) \
|
||||
nonstatic_field(Method, _intrinsic_id, u2) \
|
||||
nonstatic_field(Method, _flags, u2) \
|
||||
nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \
|
||||
volatile_nonstatic_field(Method, _code, CompiledMethod*) \
|
||||
nonstatic_field(Method, _i2i_entry, address) \
|
||||
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user