これらは, デバッグ用(開発時用)のクラス.
これらのクラスは, バイトコードが何回実行されたかを計測する. 以下の 3種類が用意されている.
デバッグ用(開発時用)のクラス (関連する develop オプションが指定されている場合にのみ使用される) (See: CountBytecodes, TraceBytecodes, StopInterpreterAt).
単に「全部で何個のバイトコードが実行されたか」を計測するだけのクラス (より正確には, そのための機能を納めた名前空間(AllStatic クラス)).
((cite: hotspot/src/share/vm/interpreter/bytecodeHistogram.hpp))
// BytecodeCounter counts the number of bytecodes executed
class BytecodeCounter: AllStatic {
初期化は AbstractInterpreter::initialize() 内で行われている.
((cite: hotspot/src/share/vm/interpreter/interpreter.cpp))
void AbstractInterpreter::initialize() {
...
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) BytecodeCounter::reset();
if (PrintBytecodeHistogram) BytecodeHistogram::reset();
if (PrintBytecodePairHistogram) BytecodePairHistogram::reset();
現在は, 以下の箇所で(のみ)記録されている.
((cite: hotspot/src/share/vm/interpreter/templateInterpreter.cpp))
void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
if (PrintBytecodeHistogram) histogram_bytecode(t);
#ifndef PRODUCT
// debugging code
if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode();
if (PrintBytecodePairHistogram) histogram_bytecode_pair(t);
((cite: hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp))
#ifdef PRODUCT
#define DO_UPDATE_INSTRUCTION_COUNT(opcode)
#else
#define DO_UPDATE_INSTRUCTION_COUNT(opcode) \
{ \
BytecodeCounter::_counter_value++; \
BytecodeHistogram::_counters[(Bytecodes::Code)opcode]++; \
if (StopInterpreterAt && StopInterpreterAt == BytecodeCounter::_counter_value) os::breakpoint(); \
if (TraceBytecodes) { \
CALL_VM((void)SharedRuntime::trace_bytecode(THREAD, 0, \
topOfStack[Interpreter::expr_index_at(1)], \
topOfStack[Interpreter::expr_index_at(2)]), \
handle_exception); \
} \
}
#endif
蓄えた結果は, デバッグ用(開発時用)の統計情報として print_statistics() 内で出力される.
((cite: hotspot/src/share/vm/runtime/java.cpp))
void print_statistics() {
...
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
BytecodeCounter::print();
}
if (PrintBytecodePairHistogram) {
BytecodePairHistogram::print();
}
print_statistics() での出力以外では, 以下の箇所で使用されている.
((cite: hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp))
void TemplateInterpreterGenerator::stop_interpreter_at() {
AddressLiteral counter(&BytecodeCounter::_counter_value);
__ load_contents(counter, G3_scratch);
AddressLiteral stop_at(&StopInterpreterAt);
__ load_ptr_contents(stop_at, G4_scratch);
__ cmp(G3_scratch, G4_scratch);
__ breakpoint_trap(Assembler::equal);
((cite: hotspot/src/share/vm/interpreter/bytecodeTracer.cpp))
if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) {
((cite: hotspot/src/share/vm/interpreter/bytecodeTracer.cpp))
void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
...
if (Verbose) {
st->print("%8d %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s",
BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code));
} else {
st->print("%8d %4d %s",
BytecodeCounter::counter_value(), bci, Bytecodes::name(code));
}
See: here for details
デバッグ用(開発時用)のクラス (関連する develop オプションが指定されている場合にのみ使用される) (See: PrintBytecodeHistogram)
単に「各バイトコードが何回実行されたか」を計測するだけのクラス (より正確には, そのための機能を納めた名前空間(AllStatic クラス)).
((cite: hotspot/src/share/vm/interpreter/bytecodeHistogram.hpp))
// BytecodeHistogram collects number of executions of bytecodes
class BytecodeHistogram: AllStatic {
初期化は AbstractInterpreter::initialize() 内で行われている.
((cite: hotspot/src/share/vm/interpreter/interpreter.cpp))
void AbstractInterpreter::initialize() {
...
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) BytecodeCounter::reset();
if (PrintBytecodeHistogram) BytecodeHistogram::reset();
if (PrintBytecodePairHistogram) BytecodePairHistogram::reset();
現在は, 以下の箇所で(のみ)記録されている.
((cite: hotspot/src/share/vm/interpreter/templateInterpreter.cpp))
void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
if (PrintBytecodeHistogram) histogram_bytecode(t);
#ifndef PRODUCT
// debugging code
if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode();
if (PrintBytecodePairHistogram) histogram_bytecode_pair(t);
((cite: hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp))
#ifdef PRODUCT
#define DO_UPDATE_INSTRUCTION_COUNT(opcode)
#else
#define DO_UPDATE_INSTRUCTION_COUNT(opcode) \
{ \
BytecodeCounter::_counter_value++; \
BytecodeHistogram::_counters[(Bytecodes::Code)opcode]++; \
if (StopInterpreterAt && StopInterpreterAt == BytecodeCounter::_counter_value) os::breakpoint(); \
if (TraceBytecodes) { \
CALL_VM((void)SharedRuntime::trace_bytecode(THREAD, 0, \
topOfStack[Interpreter::expr_index_at(1)], \
topOfStack[Interpreter::expr_index_at(2)]), \
handle_exception); \
} \
}
#endif
蓄えた結果は before_exit() 内で出力されている模様.
((cite: hotspot/src/share/vm/runtime/java.cpp))
void before_exit(JavaThread * thread) {
...
if (PrintBytecodeHistogram) {
BytecodeHistogram::print();
}
内部にはバイトコード種別分だけの大きさの配列を持っており, 各バイトコードが実行されるたびに該当するエントリをincrementしている.
((cite: hotspot/src/share/vm/interpreter/bytecodeHistogram.hpp))
NOT_PRODUCT(static int _counters[Bytecodes::number_of_codes];) // a counter for each bytecode
See: here for details
デバッグ用(開発時用)のクラス (関連する develop オプションが指定されている場合にのみ使用される) (See: PrintBytecodePairHistogram)
2個の連続したバイトコード(2-gram)単位で見て, 「それぞれのペアが何回実行されたか」を計測するだけのクラス (より正確には, そのための機能を納めた名前空間(AllStatic クラス)).
((cite: hotspot/src/share/vm/interpreter/bytecodeHistogram.hpp))
// BytecodePairHistogram collects number of executions of bytecode pairs.
// A bytecode pair is any sequence of two consequtive bytecodes.
class BytecodePairHistogram: AllStatic {
初期化は AbstractInterpreter::initialize() 内で行われている.
((cite: hotspot/src/share/vm/interpreter/interpreter.cpp))
void AbstractInterpreter::initialize() {
...
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) BytecodeCounter::reset();
if (PrintBytecodeHistogram) BytecodeHistogram::reset();
if (PrintBytecodePairHistogram) BytecodePairHistogram::reset();
現在は, 以下の箇所で(のみ)記録されている.
((cite: hotspot/src/share/vm/interpreter/templateInterpreter.cpp))
void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
if (PrintBytecodeHistogram) histogram_bytecode(t);
#ifndef PRODUCT
// debugging code
if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode();
if (PrintBytecodePairHistogram) histogram_bytecode_pair(t);
((cite: hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp))
#ifdef PRODUCT
#define DO_UPDATE_INSTRUCTION_COUNT(opcode)
#else
#define DO_UPDATE_INSTRUCTION_COUNT(opcode) \
{ \
BytecodeCounter::_counter_value++; \
BytecodeHistogram::_counters[(Bytecodes::Code)opcode]++; \
if (StopInterpreterAt && StopInterpreterAt == BytecodeCounter::_counter_value) os::breakpoint(); \
if (TraceBytecodes) { \
CALL_VM((void)SharedRuntime::trace_bytecode(THREAD, 0, \
topOfStack[Interpreter::expr_index_at(1)], \
topOfStack[Interpreter::expr_index_at(2)]), \
handle_exception); \
} \
}
#endif
蓄えた結果は, デバッグ用(開発時用)の統計情報として print_statistics() 内で出力される.
((cite: hotspot/src/share/vm/runtime/java.cpp))
void print_statistics() {
...
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
BytecodeCounter::print();
}
if (PrintBytecodePairHistogram) {
BytecodePairHistogram::print();
}
内部には「バイトコード種別数の2乗」の大きさの配列を持っており, 各バイトコードが実行されるたびに該当するエントリをincrementしている.
((cite: hotspot/src/share/vm/interpreter/bytecodeHistogram.hpp))
...
number_of_pairs = number_of_codes * number_of_codes
...
NOT_PRODUCT(static int _counters[number_of_pairs];) // a counter for each pair
See: here for details
BytecodeHistogram クラス及び BytecodePairHistogram クラス用の補助クラス.
BytecodeHistogram クラスや BytecodePairHistogram クラスの中身をソートして出力する処理で使用される一時オブジェクト(ResourceObjクラス).
((cite: hotspot/src/share/vm/interpreter/bytecodeHistogram.cpp))
// Helper class for sorting
class HistoEntry: public ResourceObj {
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.