上一篇主要分析了HotSpot模板解释器和汇编器的实现,相比于c解释器,通过汇编器和模板解释器将字节码指令编译成汇编指令,显著提升了HotSpot的性能。除此之外HotSpot更进一步实现了C1,C2编译器用于在服务端选择性的进一步编译优化指令。提供了Tiered分层编译,内置LLVM,AOT编译等,此外基于Java语言实现的 GraalVm 全栈编译器也势头强劲。
一.初始化C1编译器
hotspot/src/share/vm/runtime/thread.cpp
创建HotSpot虚拟机时会初始化编译器
jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
CompileBroker::compilation_init(CHECK_JNI_ERR);
}
hotspot/src/share/vm/compiler/compileBroker.cpp
void CompileBroker::compilation_init(TRAPS) {
init_compiler_sweeper_threads(c1_count, c2_count);
}
hotspot/src/share/vm/compiler/compileBroker.cpp
按c1_compiler_count值创建多个编译线程,线程持有编译任务队列
void CompileBroker::init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count) {
_c1_compile_queue = new CompileQueue("C1 compile queue");
for (int i = 0; i < c1_compiler_count; i++) {
CompilerCounters* counters = new CompilerCounters();
make_thread(name_buffer, _c1_compile_queue, counters, _compilers[1], compiler_thread, CHECK);
}
}
hotspot/src/share/vm/compiler/compileBroker.cpp
JavaThread* CompileBroker::make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters,
AbstractCompiler* comp, bool compiler_thread, TRAPS) {
thread = new CompilerThread(queue, counters);
Thread::start(thread);
}
hotspot/src/share/vm/runtime/thread.cpp
初始化编译线程时挂载一个执行函数compiler_thread_entry
CompilerThread::CompilerThread(CompileQueue* queue,
CompilerCounters* counters)
: JavaThread(&compiler_thread_entry) {
_queue = queue;
_counters = counters;
_buffer_blob = NULL;
_compiler = NULL;
}
hotspot/src/share/vm/runtime/thread.cpp
执行函数会在线程创建完成之后调用compiler_thread_loop,通知编译器开始线程循环
static void compiler_thread_entry(JavaThread* thread, TRAPS) {
CompileBroker::compiler_thread_loop();
}
hotspot/src/share/vm/compiler/compileBroker.cpp
while循环执行,从任务队列中取出已提交的编译任务,调用invoke_compiler_on_method派发编译
void CompileBroker::compiler_thread_loop() {
CompilerThread* thread = CompilerThread::current();
CompileQueue* queue = thread->queue();
//初始化编译环境
init_compiler_runtime()
//循环从编译任务队列里取编译任务并执行
while (!is_compilation_disabled_forever()) {
CompileTask* task = queue->get();
// Assign the task to the current thread. Mark this compilation
// thread as active for the profiler.
CompileTaskWrapper ctw(task);
nmethodLocker result_handle; // (handle for the nmethod produced by this task)
task->set_code_handle(&result_handle);
methodHandle method(thread, task->method());
//......
//编译任务
invoke_compiler_on_method(task);
//......
// Shut down compiler runtime
shutdown_compiler_runtime(thread->compiler(), thread);
}
hotspot/src/share/vm/compiler/compileBroker.cpp
收到编译任务后,从task取出对应需要使用的编译器,调用compile_method
void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
CompilerThread* thread = CompilerThread::current();
uint compile_id = task->compile_id();
int osr_bci = task->osr_bci();
bool is_osr = (osr_bci != standard_entry_bci);
const int task_level = task->comp_level();
AbstractCompiler* comp = task->compiler();
methodHandle method(thread, task->method());
// Allocate a new set of JNI handles.
push_jni_handle_block();
Method* target_handle = task->method();
int compilable = ciEnv::MethodCompilable;
{
ciEnv ci_env(task, system_dictionary_modification_counter);
//执行编译
comp->compile_method(&ci_env, target, osr_bci, directive);
// Copy this bit to the enclosing block:
compilable = ci_env.compilable();
post_compile(thread, task, event, !ci_env.failing(), &ci_env);
}
// Remove the JNI handle block after the ciEnv destructor has run in
// the previous block.
pop_jni_handle_block();
// Disable compilation, if required.
switch (compilable) {
case ciEnv::MethodCompilable_never:
if (is_osr)
method->set_not_osr_compilable_quietly();
else
method->set_not_compilable_quietly();
break;
case ciEnv::MethodCompilable_not_at_tier:
if (is_osr)
method->set_not_osr_compilable_quietly(task_level);
else
method->set_not_compilable_quietly(task_level);
break;
}
}
hotspot/src/share/vm/c1/c1_Compiler.cpp
执行Compilation初始化,Compilation构造函数将调用compile_method
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
Compilation c(this, env, method, entry_bci, buffer_blob, directive);
}
二.触发和提交编译任务
hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp
编译器环境初始化好以后循环等待编译任务到来,HosSpot中在generate_normal_entry这个entry_point会埋点统计当前方法的执行次数,当方法执行次数超过指定阀值时会触发JIT
address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
......
// Handle overflow of counter and compile method
__ bind