これらは, JIT コンパイル処理を行う CompilerThread にコンパイル要求を伝えるためのクラス (See: here for details).
JIT コンパイル要求に対する broker(仲介役) 的なクラス (より正確には, そのための機能を納めた名前空間(AllStatic クラス)).
コンパイル要求はまず CompileBroker に伝えられ, そこから実際に処理を行う CompilerThread に渡される.
(なお, 実際に使用する JIT コンパイラの種類は CompileBroker によって隠蔽されている. そのため JIT コンパイル要求を出すコードからは C1, C2, Shark の違いは見えない. どの場合も CompilerBroker に要求を出すだけになる)
また, CompileBroker クラスはコンパイラスレッドを作成する機能も提供している (make_compiler_thread, init_compiler_threads).
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
// Compilation
//
// The broker for all compilation requests.
class CompileBroker: AllStatic {
このクラスの CompileBroker::compile_method() メソッドが JIT コンパイル要求を出す処理のエントリポイントになっている. 様々な処理からこのメソッドが呼び出されることで JIT コンパイルが開始される.
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
static nmethod* compile_method(methodHandle method,
int osr_bci,
int comp_level,
methodHandle hot_method,
int hot_count,
const char* comment, TRAPS);
See: here for details
「JIT コンパイル要求」を表すためのクラス.
CompilerBroker に届けられたコンパイル要求は, CompileTask オブジェクトとして CompilerThread に送られる.
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
// CompileTask
//
// An entry in the compile queue. It represents a pending or current
// compilation.
class CompileTask : public CHeapObj {
See: here for details
CompileTask オブジェクトを詰めるためのキュー.
CompilerBroker に届けられたコンパイル要求は, このキューを介して CompilerThread に伝えられる.
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
// CompileQueue
//
// A list of CompileTasks.
class CompileQueue : public CHeapObj {
以下の箇所に(のみ)格納されている.
(C1 用と C2 用の 2本が用意されている. Tiered でなければどちらか一方だけ/Tiered なら両方が使用される)
(C1 用)
(C2/Shark 用)
(なお CompilerThread 側には, CompilerThread の生成時に使用する CompilerQueue が引数として渡されている)
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
static CompileQueue* _c2_method_queue;
static CompileQueue* _c1_method_queue;
CompileBroker::init_compiler_threads() 内で(のみ)生成されている.
See: here for details
CompileTask クラス用のユーティリティ・クラス.
ソースコード中のあるスコープの間だけ, CompilerThread に CompileTask をセットするための一時オブジェクト(StackObjクラス).
(また, CompileLog を用いたログ出力の開始/終了処理も行っているほか, デストラクタ内では CompileTask へのロック待ちがいた場合, 完了したことを notifyAll() で通知したりもしている)
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
// CompileTaskWrapper
//
// Assign this task to the current thread. Deallocate the task
// when the compilation is complete.
class CompileTaskWrapper : StackObj {
以下の箇所で(のみ)使用されている.
(コンストラクタでカレントスレッドに指定の CompileTask がセットされ, デストラクタで終了アドレスが記録される)
((cite: hotspot/src/share/vm/compiler/compileBroker.cpp))
CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
CompilerThread* thread = CompilerThread::current();
thread->set_task(task);
CompileLog* log = thread->log();
if (log != NULL) task->log_task_start(log);
}
CompileTaskWrapper::~CompileTaskWrapper() {
CompilerThread* thread = CompilerThread::current();
CompileTask* task = thread->task();
CompileLog* log = thread->log();
if (log != NULL) task->log_task_done(log);
thread->set_task(NULL);
task->set_code_handle(NULL);
DEBUG_ONLY(thread->set_env((ciEnv*)badAddress));
if (task->is_blocking()) {
MutexLocker notifier(task->lock(), thread);
task->mark_complete();
// Notify the waiting thread that the compilation has completed.
task->lock()->notify_all();
} else {
task->mark_complete();
// By convention, the compiling thread is responsible for
// recycling a non-blocking CompileTask.
CompileBroker::free_task(task);
}
}
See: here for details
JIT コンパイル処理に関する統計情報を溜めていくためのパフォーマンスカウンタ. 内部的には PerfData を用いた記録を行う.
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
// CompilerCounters
//
// Per Compiler Performance Counters.
//
class CompilerCounters : public CHeapObj {
各 CompilerThread オブジェクトの _counters フィールドに(のみ)格納されている.
CompileBroker::init_compiler_threads() 内で(のみ)生成されている.
((cite: hotspot/src/share/vm/compiler/compileBroker.cpp))
void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) {
...
for (int i = 0; i < c2_compiler_count; i++) {
// Create a name for our thread.
sprintf(name_buffer, "C2 CompilerThread%d", i);
CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_method_queue, counters, CHECK);
_method_threads->append(new_thread);
}
for (int i = c2_compiler_count; i < compiler_count; i++) {
// Create a name for our thread.
sprintf(name_buffer, "C1 CompilerThread%d", i);
CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_method_queue, counters, CHECK);
_method_threads->append(new_thread);
}
CompileBroker::compiler_thread_loop() 内で参照されている (#TODO 他の使用箇所)
内部には, 以下の PerfCounter を備えている.
((cite: hotspot/src/share/vm/compiler/compileBroker.hpp))
char _current_method[cmname_buffer_length];
PerfStringVariable* _perf_current_method;
int _compile_type;
PerfVariable* _perf_compile_type;
PerfCounter* _perf_time;
PerfCounter* _perf_compiles;
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.