目录
5、AdvancedThresholdPolicy::select_task
在上一篇《Hotspot 方法编译之CompilationPolicy 源码解析》中研究AdvancedThresholdPolicy::submit_compile方法的实现时,触发方法编译是通过CompileBroker::compile_method方法完成。本篇博客就顺着compile_method方法的实现研究CompileBroker依赖的相关类的使用与调用关系。
一、CompileTask
1、定义
CompileTask继承自CHeapObj,表示编译队列中的一个编译任务,其定义位于hospot src/share/vm/compiler/compileBroker.hpp中。CompileTask定义的私有属性如下:
- _task_free_list:CompileTask*,空闲的编译任务队列
- _lock:Monitor*,该任务的锁
- _compile_id:uint
- _method:Method*,该编译任务对应的方法
- _method_holder:jobject,_method所属的klass的引用
- _osr_bci:int,栈上替换方法相对于字节码基地址的偏移
- _is_complete/_is_success/_is_blocking:bool,编译任务的状态
- _comp_level:int,编译级别
- _num_inlined_bytecodes:int,栈上替换方法对应的字节码的字节数
- _code_handle:nmethodLocker*,nmethodLocker是nmethod的一个容器,用来保存编译完成的代码
- _next/_prev:CompileTask*,编译任务队列中的下一个和上一个任务
除此之外,还有如下几个用来CompileTask初始化时打印日志的属性:
- _time_queued:jlong,取值os::elapsed_counter(),表示JVM启动到现在的累计时间
- _hot_method:Method*,触发这个方法编译的方法
- _hot_method_holder:jobject,_hot_method所属的klass的引用
- _hot_count:int,触发方法编译的调用次数
- _comment:char*,编译任务的备注
- _failure_reason:char*,编译任务失败原因
CompileTask定义方法大部分是属性操作相关的和日志打印相关的,重点关注用来创建CompileTask实例的allocate方法,用来释放CompileTask实例内存的free方法,用来初始化CompileTask的initialize方法的实现。
2、allocate/free/initialize方法
allocate方法是和initialize方法配合使用的,其调用方只有一个CompileBroker::create_compile_task,调用链如下:
CompileBroker::create_compile_task的实现也很简单,如下图:
free方法的调用链如下;
当编译完成等CompileTask不再使用时就会释放掉。这三个方法实现的源码说明如下:
/**
* Allocate a CompileTask, from the free list if possible.
*/
CompileTask* CompileTask::allocate() {
//获取锁CompileTaskAlloc_lock
MutexLocker locker(CompileTaskAlloc_lock);
CompileTask* task = NULL;
//_task_free_list不为空,则取头元素
if (_task_free_list != NULL) {
task = _task_free_list;
_task_free_list = task->next();
task->set_next(NULL);
} else {
//_task_free_list为空,则创建一个新的
task = new CompileTask();
DEBUG_ONLY(_num_allocated_tasks++;)
assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?");
task->set_next(NULL);
task->set_is_free(true);
}
assert(task->is_free(), "Task must be free.");
//将free置为false标识已经被占用
task->set_is_free(false);
return task;
}
/**
* Add a task to the free list.
*/
void CompileTask::free(CompileTask* task) {
//获取锁CompileTaskAlloc_lock
MutexLocker locker(CompileTaskAlloc_lock);
if (!task->is_free()) {
//将code置为null
task->set_code(NULL);
assert(!task->lock()->is_locked(), "Should not be locked when freed");
//将jobject包含的对象指针销毁
JNIHandles::destroy_global(task->_method_holder);
JNIHandles::destroy_global(task->_hot_method_holder);
//free置为true,插入到_task_free_list链表前面
task->set_is_free(true);
task->set_next(_task_free_list);
_task_free_list = task;
}
}
void CompileTask::initialize(int compile_id,
methodHandle method,
int osr_bci,
int comp_level,
methodHandle hot_method,
int hot_count,
const char* comment,
bool is_blocking) {
assert(!_lo