目录
五、AbstractInterpreterGenerator
六、TemplateInterpreterGenerator
2、set_entry_points_for_all_bytes
在上一篇《Hotspot 方法调用之Interpreter 源码解析》中讲到Interpreter通过宏可以继承自CppInterpreter或者TemplateInterpreter,前者称为C++解释器,每个指令都对应一段C++代码,通过switch/case的方式处理字节码,后者称为模板解释器,每个指令对应一段汇编指令,通过指令模板的方式处理字节码,JVM默认使用模板解释器。下面我们就详细探讨下TemplateInterpreter的相关类及其实现。
一、AbstractInterpreter
AbstractInterpreter的定义位于hotspot src/share/vm/interpreter/abstractInterpreter.hpp中,是CppInterpreter和TemplateInterpreter共同的基类,用来抽象平台独立的解释器相关的属性和方法。AbstractInterpreter定义的属性都是protected,如下:
- _code:StubQueue*,用来保存生成的汇编代码的
- _notice_safepoints:bool,是否激活了安全点机制
- _native_entry_begin:address,JIT编译器产生的本地代码在内存中的起始位置
- _native_entry_end:address,JIT编译器产生的本地代码在内存中的终止位置
- _entry_table:address数组,处理不同类型的方法的方法调用的入口地址,数组的长度就是枚举number_of_method_entries的值
- _native_abi_to_tosca:address数组,处理不同类型的本地方法调用返回值的入口地址,数组的长度是枚举number_of_result_handlers的值,目前为10
- _slow_signature_handler:address,本地方法生成签名的入口地址
- _rethrow_exception_entry:address,重新抛出异常的入口地址
AbstractInterpreter定义了一个表示方法类型的枚举MethodKind,每个类型都对应_entry_table中一个数组元素,即一个处理该类型方法的方法调用的入口地址,如下图:
枚举number_of_result_handlers的定义如下:
AbstractInterpreter定义的public方法可以分为以下几种:
- 方法类型操作相关的,如method_kind,entry_for_kind,set_entry_for_kind等
- 解释器运行时支持相关的,如deopt_entry,deopt_continue_after_entry,deopt_reexecute_entry等
- 本地方法调用支持相关的,如slow_signature_handler,result_handler,in_native_entry等
- 解释器工具方法,如local_offset_in_bytes,oop_addr_in_slot,long_in_slot,set_long_in_slot等
重点关注其initialize方法的实现,源码说明如下:
void AbstractInterpreter::initialize() {
//避免二次初始化
if (_code != NULL) return;
// make sure 'imported' classes are initialized
//BytecodeCounter统计字节码总的执行次数
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) BytecodeCounter::reset();
//BytecodeHistogram统计每个字节码的执行次数
if (PrintBytecodeHistogram) BytecodeHistogram::reset();
//BytecodePairHistogram统计字节码对的执行次数,字节码对是指两个连续的字节码
if (PrintBytecodePairHistogram) BytecodePairHistogram::reset();
//InvocationCounters用于保存方法调用的次数,当次数达到某个阈值时会触发某个动作执行
InvocationCounter::reinitialize(DelayCompilationDuringStartup);
}
其调用链如下:
二、TemplateInterpreter
1、定义
TemplateInterpreter继承自AbstractInterpreter,其定义在同目录下的templateInterpreter.hpp中。TemplateInterpreter在此基础上增加了很多的完成特定功能的函数的调用入口,如下图:
EntryPoint就是一个address的数组的包装类,如下图所示:
其中number_of_states是枚举TosState中表示state个数的枚举值,如下图:
TosState枚举用来表示字节码指令执行前后栈顶的值的类型,栈顶的值可能保存在一个或者多个CPU寄存器中,需要通过值类型正确的读取值,将栈顶的值保存到一个或者多个寄存器中的技术就称为栈顶缓存技术,默认情况下栈顶的值保存在rax寄存器中。如果TosState为vtos则表示未使用栈顶缓存。
DispatchTable是一个address二维数组的包装类,其定义如下:
其中BitsPerByte表示一个字节多少位,固定值8。
TemplateInterpreter新增的方法主要有以下几种:
- 获取特定TosState的调用入口相关的,如continuation,dispatch_table,invoke_return_entry_table等
- 逆向优化相关的,如deopt_continue_after_entry,bytecode_should_reexecute等
TemplateInterpreter中定义的都是平台无关的部分,跟平台相关的部分通过宏的方式引入,如下图:
templateInterpreter_x86.hpp也比较简单,主要添加了InterpreterCodeSize常量的定义,如下图:
2、initialize
重点关注TemplateInterpreter initialize方法的实现,源码说明如下 :
void TemplateInterpreter::initialize() {
if (_code != NULL) return;
//校验字节码的个数必须小于等于DispatchTable的长度
assert((int)Bytecodes::number_of_codes <= (int)DispatchTable::length,
"dispatc