8037970: make PrintMethodData a diagnostic options
Summary: make PrintMethodData a diagnostic options for performance investigation
Reviewed-by: kvn, iveresov
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Mon Mar 31 10:35:06 2014 +0200
@@ -135,6 +135,14 @@
}
}
+void ClassLoaderData::methods_do(void f(Method*)) {
+ for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
+ if (k->oop_is_instance()) {
+ InstanceKlass::cast(k)->methods_do(f);
+ }
+ }
+}
+
void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) {
// Lock to avoid classes being modified/added/removed during iteration
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
@@ -624,6 +632,12 @@
}
}
+void ClassLoaderDataGraph::methods_do(void f(Method*)) {
+ for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+ cld->methods_do(f);
+ }
+}
+
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->loaded_classes_do(klass_closure);
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Mon Mar 31 10:35:06 2014 +0200
@@ -78,6 +78,7 @@
static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
static void classes_do(KlassClosure* klass_closure);
static void classes_do(void f(Klass* const));
+ static void methods_do(void f(Method*));
static void loaded_classes_do(KlassClosure* klass_closure);
static void classes_unloading_do(void f(Klass* const));
static bool do_unloading(BoolObjectClosure* is_alive);
@@ -189,6 +190,7 @@
void classes_do(void f(Klass*));
void loaded_classes_do(KlassClosure* klass_closure);
void classes_do(void f(InstanceKlass*));
+ void methods_do(void f(Method*));
// Deallocate free list during class unloading.
void free_deallocate_list();
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Mon Mar 31 10:35:06 2014 +0200
@@ -35,8 +35,6 @@
#include "runtime/timer.hpp"
-#ifndef PRODUCT
-
// Standard closure for BytecodeTracer: prints the current bytecode
// and its attributes using bytecode-specific information.
@@ -600,4 +598,3 @@
}
}
}
-#endif // PRODUCT
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp Mon Mar 31 10:35:06 2014 +0200
@@ -34,8 +34,7 @@
// By specialising the BytecodeClosure, all kinds of bytecode traces can
// be done.
-#ifndef PRODUCT
-// class BytecodeTracer is only used by TraceBytecodes option
+// class BytecodeTracer is used by TraceBytecodes option and PrintMethodData
class BytecodeClosure;
class BytecodeTracer: AllStatic {
@@ -60,6 +59,4 @@
virtual void trace(methodHandle method, address bcp, outputStream* st) = 0;
};
-#endif // !PRODUCT
-
#endif // SHARE_VM_INTERPRETER_BYTECODETRACER_HPP
--- a/hotspot/src/share/vm/oops/method.cpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/oops/method.cpp Mon Mar 31 10:35:06 2014 +0200
@@ -329,14 +329,12 @@
}
}
-#ifndef PRODUCT
void Method::print_invocation_count() {
if (is_static()) tty->print("static ");
if (is_final()) tty->print("final ");
if (is_synchronized()) tty->print("synchronized ");
if (is_native()) tty->print("native ");
- method_holder()->name()->print_symbol_on(tty);
- tty->print(".");
+ tty->print("%s::", method_holder()->external_name());
name()->print_symbol_on(tty);
signature()->print_symbol_on(tty);
@@ -349,12 +347,12 @@
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());
+#ifndef PRODUCT
if (CountCompiledCalls) {
tty->print_cr (" compiled_invocation_count: %8d ", compiled_invocation_count());
}
-
+#endif
}
-#endif
// Build a MethodData* object to hold information about this method
// collected in the interpreter.
@@ -1443,10 +1441,6 @@
#endif // !PRODUCT || INCLUDE_JVMTI
-//-----------------------------------------------------------------------------------
-// Non-product code
-
-#ifndef PRODUCT
void Method::print_codes_on(outputStream* st) const {
print_codes_on(0, code_size(), st);
}
@@ -1460,7 +1454,6 @@
BytecodeTracer::set_closure(BytecodeTracer::std_closure());
while (s.next() >= 0) BytecodeTracer::trace(mh, s.bcp(), st);
}
-#endif // not PRODUCT
// Simple compression of line number tables. We use a regular compressed stream, except that we compress deltas
--- a/hotspot/src/share/vm/oops/method.hpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/oops/method.hpp Mon Mar 31 10:35:06 2014 +0200
@@ -429,6 +429,9 @@
#ifndef PRODUCT
int compiled_invocation_count() const { return _compiled_invocation_count; }
void set_compiled_invocation_count(int count) { _compiled_invocation_count = count; }
+#else
+ // for PrintMethodData in a product build
+ int compiled_invocation_count() const { return 0; }
#endif // not PRODUCT
// Clear (non-shared space) pointers which could not be relevant
@@ -497,10 +500,8 @@
// Interpreter oopmap support
void mask_for(int bci, InterpreterOopMap* mask);
-#ifndef PRODUCT
// operations on invocation counter
void print_invocation_count();
-#endif
// byte codes
void set_code(address code) { return constMethod()->set_code(code); }
@@ -509,8 +510,8 @@
// prints byte codes
void print_codes() const { print_codes_on(tty); }
- void print_codes_on(outputStream* st) const PRODUCT_RETURN;
- void print_codes_on(int from, int to, outputStream* st) const PRODUCT_RETURN;
+ void print_codes_on(outputStream* st) const;
+ void print_codes_on(int from, int to, outputStream* st) const;
// method parameters
bool has_method_parameters() const
--- a/hotspot/src/share/vm/oops/methodData.cpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/oops/methodData.cpp Mon Mar 31 10:35:06 2014 +0200
@@ -115,7 +115,6 @@
print_data_on(st, print_data_on_helper(md));
}
-#ifndef PRODUCT
void ProfileData::print_shared(outputStream* st, const char* name, const char* extra) const {
st->print("bci: %d", bci());
st->fill_to(tab_width_one);
@@ -138,7 +137,6 @@
void ProfileData::tab(outputStream* st, bool first) const {
st->fill_to(first ? tab_width_one : tab_width_two);
}
-#endif // !PRODUCT
// ==================================================================
// BitData
@@ -147,23 +145,19 @@
// whether a checkcast bytecode has seen a null value.
-#ifndef PRODUCT
void BitData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "BitData", extra);
}
-#endif // !PRODUCT
// ==================================================================
// CounterData
//
// A CounterData corresponds to a simple counter.
-#ifndef PRODUCT
void CounterData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "CounterData", extra);
st->print_cr("count(%u)", count());
}
-#endif // !PRODUCT
// ==================================================================
// JumpData
@@ -188,12 +182,10 @@
set_displacement(offset);
}
-#ifndef PRODUCT
void JumpData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "JumpData", extra);
st->print_cr("taken(%u) displacement(%d)", taken(), displacement());
}
-#endif // !PRODUCT
int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
// Parameter profiling include the receiver
@@ -342,7 +334,6 @@
return MethodData::profile_arguments();
}
-#ifndef PRODUCT
void TypeEntries::print_klass(outputStream* st, intptr_t k) {
if (is_type_none(k)) {
st->print("none");
@@ -398,7 +389,6 @@
_ret.print_data_on(st);
}
}
-#endif
// ==================================================================
// ReceiverTypeData
@@ -417,7 +407,6 @@
}
}
-#ifndef PRODUCT
void ReceiverTypeData::print_receiver_data_on(outputStream* st) const {
uint row;
int entries = 0;
@@ -447,7 +436,6 @@
print_shared(st, "VirtualCallData", extra);
print_receiver_data_on(st);
}
-#endif // !PRODUCT
// ==================================================================
// RetData
@@ -499,7 +487,6 @@
}
#endif // CC_INTERP
-#ifndef PRODUCT
void RetData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "RetData", extra);
uint row;
@@ -516,7 +503,6 @@
}
}
}
-#endif // !PRODUCT
// ==================================================================
// BranchData
@@ -534,7 +520,6 @@
set_displacement(offset);
}
-#ifndef PRODUCT
void BranchData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "BranchData", extra);
st->print_cr("taken(%u) displacement(%d)",
@@ -542,7 +527,6 @@
tab(st);
st->print_cr("not taken(%u)", not_taken());
}
-#endif
// ==================================================================
// MultiBranchData
@@ -608,7 +592,6 @@
}
}
-#ifndef PRODUCT
void MultiBranchData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "MultiBranchData", extra);
st->print_cr("default_count(%u) displacement(%d)",
@@ -620,9 +603,7 @@
count_at(i), displacement_at(i));
}
}
-#endif
-#ifndef PRODUCT
void ArgInfoData::print_data_on(outputStream* st, const char* extra) const {
print_shared(st, "ArgInfoData", extra);
int nargs = number_of_args();
@@ -632,8 +613,6 @@
st->cr();
}
-#endif
-
int ParametersTypeData::compute_cell_count(Method* m) {
if (!MethodData::profile_parameters_for_method(m)) {
return 0;
@@ -654,7 +633,6 @@
return MethodData::profile_parameters();
}
-#ifndef PRODUCT
void ParametersTypeData::print_data_on(outputStream* st, const char* extra) const {
st->print("parameter types", extra);
_parameters.print_data_on(st);
@@ -666,7 +644,6 @@
method()->print_short_name(st);
st->cr();
}
-#endif
// ==================================================================
// MethodData*
@@ -1359,8 +1336,6 @@
// Printing
-#ifndef PRODUCT
-
void MethodData::print_on(outputStream* st) const {
assert(is_methodData(), "should be method data");
st->print("method data for ");
@@ -1369,15 +1344,12 @@
print_data_on(st);
}
-#endif //PRODUCT
-
void MethodData::print_value_on(outputStream* st) const {
assert(is_methodData(), "should be method data");
st->print("method data for ");
method()->print_value_on(st);
}
-#ifndef PRODUCT
void MethodData::print_data_on(outputStream* st) const {
ResourceMark rm;
ProfileData* data = first_data();
@@ -1418,7 +1390,6 @@
if (dp >= end) return;
}
}
-#endif
#if INCLUDE_SERVICES
// Size Statistics
--- a/hotspot/src/share/vm/oops/methodData.hpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/oops/methodData.hpp Mon Mar 31 10:35:06 2014 +0200
@@ -280,12 +280,10 @@
friend class ReturnTypeEntry;
friend class TypeStackSlotEntries;
private:
-#ifndef PRODUCT
enum {
tab_width_one = 16,
tab_width_two = 36
};
-#endif // !PRODUCT
// This is a pointer to a section of profiling data.
DataLayout* _data;
@@ -521,10 +519,8 @@
void print_data_on(outputStream* st, const MethodData* md) const;
-#ifndef PRODUCT
void print_shared(outputStream* st, const char* name, const char* extra) const;
void tab(outputStream* st, bool first = false) const;
-#endif
};
// BitData
@@ -583,9 +579,7 @@
}
#endif // CC_INTERP
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// CounterData
@@ -646,9 +640,7 @@
}
#endif // CC_INTERP
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// JumpData
@@ -733,9 +725,7 @@
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// Entries in a ProfileData object to record types: it can either be
@@ -808,9 +798,7 @@
return with_status((intptr_t)k, in);
}
-#ifndef PRODUCT
static void print_klass(outputStream* st, intptr_t k);
-#endif
// GC support
static bool is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p);
@@ -919,9 +907,7 @@
// GC support
void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
-#ifndef PRODUCT
void print_data_on(outputStream* st) const;
-#endif
};
// Type entry used for return from a call. A single cell to record the
@@ -964,9 +950,7 @@
// GC support
void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
-#ifndef PRODUCT
void print_data_on(outputStream* st) const;
-#endif
};
// Entries to collect type information at a call: contains arguments
@@ -1144,9 +1128,7 @@
}
}
-#ifndef PRODUCT
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// ReceiverTypeData
@@ -1288,10 +1270,8 @@
}
#endif // CC_INTERP
-#ifndef PRODUCT
void print_receiver_data_on(outputStream* st) const;
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// VirtualCallData
@@ -1332,9 +1312,7 @@
}
#endif // CC_INTERP
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// VirtualCallTypeData
@@ -1458,9 +1436,7 @@
}
}
-#ifndef PRODUCT
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// RetData
@@ -1561,9 +1537,7 @@
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// BranchData
@@ -1639,9 +1613,7 @@
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// ArrayData
@@ -1832,9 +1804,7 @@
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
class ArgInfoData : public ArrayData {
@@ -1859,9 +1829,7 @@
array_set_int_at(arg, val);
}
-#ifndef PRODUCT
void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// ParametersTypeData
@@ -1920,9 +1888,7 @@
_parameters.clean_weak_klass_links(is_alive_closure);
}
-#ifndef PRODUCT
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
static ByteSize stack_slot_offset(int i) {
return cell_offset(stack_slot_local_offset(i));
@@ -1976,9 +1942,7 @@
set_intptr_at(method_offset, (intptr_t)m);
}
-#ifndef PRODUCT
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
-#endif
};
// MethodData*
@@ -2457,15 +2421,11 @@
void set_size(int object_size_in_bytes) { _size = object_size_in_bytes; }
// Printing
-#ifndef PRODUCT
void print_on (outputStream* st) const;
-#endif
void print_value_on(outputStream* st) const;
-#ifndef PRODUCT
// printing support for method data
void print_data_on(outputStream* st) const;
-#endif
const char* internal_name() const { return "{method data}"; }
--- a/hotspot/src/share/vm/runtime/globals.hpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Mar 31 10:35:06 2014 +0200
@@ -2832,7 +2832,7 @@
"number of method invocations/branches (expressed as % of " \
"CompileThreshold) before using the method's profile") \
\
- develop(bool, PrintMethodData, false, \
+ diagnostic(bool, PrintMethodData, false, \
"Print the results of +ProfileInterpreter at end of run") \
\
develop(bool, VerifyDataPointer, trueInDebug, \
--- a/hotspot/src/share/vm/runtime/java.cpp Mon Mar 31 09:08:53 2014 +0200
+++ b/hotspot/src/share/vm/runtime/java.cpp Mon Mar 31 10:35:06 2014 +0200
@@ -98,6 +98,59 @@
#endif
+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());
+}
+
+void collect_profiled_methods(Method* m) {
+ Thread* thread = Thread::current();
+ // This HandleMark prevents a huge amount of handles from being added
+ // to the metadata_handles() array on the thread.
+ HandleMark hm(thread);
+ methodHandle mh(thread, m);
+ if ((m->method_data() != NULL) &&
+ (PrintMethodData || CompilerOracle::should_print(mh))) {
+ collected_profiled_methods->push(m);
+ }
+}
+
+void print_method_profiling_data() {
+ if (ProfileInterpreter COMPILER1_PRESENT(|| C1UpdateMethodData)) {
+ ResourceMark rm;
+ HandleMark hm;
+ collected_profiled_methods = new GrowableArray<Method*>(1024);
+ ClassLoaderDataGraph::methods_do(collect_profiled_methods);
+ collected_profiled_methods->sort(&compare_methods);
+
+ int count = collected_profiled_methods->length();
+ int total_size = 0;
+ if (count > 0) {
+ for (int index = 0; index < count; index++) {
+ Method* m = collected_profiled_methods->at(index);
+ ttyLocker ttyl;
+ tty->print_cr("------------------------------------------------------------------------");
+ m->print_invocation_count();
+ tty->print_cr(" mdo size: %d bytes", m->method_data()->size_in_bytes());
+ tty->cr();
+ // Dump data on parameters if any
+ if (m->method_data() != NULL && m->method_data()->parameters_type_data() != NULL) {
+ tty->fill_to(2);
+ m->method_data()->parameters_type_data()->print_data_on(tty);
+ }
+ m->print_codes();
+ total_size += m->method_data()->size_in_bytes();
+ }
+ tty->print_cr("------------------------------------------------------------------------");
+ tty->print_cr("Total MDO size: %d bytes", total_size);
+ }
+ }
+}
+
+
#ifndef PRODUCT
// Statistics printing (method invocation histogram)
@@ -111,26 +164,6 @@
}
-GrowableArray<Method*>* collected_profiled_methods;
-
-void collect_profiled_methods(Method* m) {
- Thread* thread = Thread::current();
- // This HandleMark prevents a huge amount of handles from being added
- // to the metadata_handles() array on the thread.
- HandleMark hm(thread);
- methodHandle mh(thread, m);
- if ((m->method_data() != NULL) &&
- (PrintMethodData || CompilerOracle::should_print(mh))) {
- collected_profiled_methods->push(m);
- }
-}
-
-
-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());
-}
void print_method_invocation_histogram() {
@@ -173,37 +206,6 @@
SharedRuntime::print_call_statistics(comp_total);
}
-void print_method_profiling_data() {
- ResourceMark rm;
- HandleMark hm;
- collected_profiled_methods = new GrowableArray<Method*>(1024);
- SystemDictionary::methods_do(collect_profiled_methods);
- collected_profiled_methods->sort(&compare_methods);
-
- int count = collected_profiled_methods->length();
- int total_size = 0;
- if (count > 0) {
- for (int index = 0; index < count; index++) {
- Method* m = collected_profiled_methods->at(index);
- ttyLocker ttyl;
- tty->print_cr("------------------------------------------------------------------------");
- //m->print_name(tty);
- m->print_invocation_count();
- tty->print_cr(" mdo size: %d bytes", m->method_data()->size_in_bytes());
- tty->cr();
- // Dump data on parameters if any
- if (m->method_data() != NULL && m->method_data()->parameters_type_data() != NULL) {
- tty->fill_to(2);
- m->method_data()->parameters_type_data()->print_data_on(tty);
- }
- m->print_codes();
- total_size += m->method_data()->size_in_bytes();
- }
- tty->print_cr("------------------------------------------------------------------------");
- tty->print_cr("Total MDO size: %d bytes", total_size);
- }
-}
-
void print_bytecode_count() {
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
tty->print_cr("[BytecodeCounter::counter_value = %d]", BytecodeCounter::counter_value());
@@ -281,9 +283,9 @@
if (CountCompiledCalls) {
print_method_invocation_histogram();
}
- if (ProfileInterpreter COMPILER1_PRESENT(|| C1UpdateMethodData)) {
- print_method_profiling_data();
- }
+
+ print_method_profiling_data();
+
if (TimeCompiler) {
COMPILER2_PRESENT(Compile::print_timers();)
}
@@ -373,6 +375,10 @@
void print_statistics() {
+ if (PrintMethodData) {
+ print_method_profiling_data();
+ }
+
if (CITime) {
CompileBroker::print_times();
}