模板解释器
解释器如果按照前述的switch-case方式执行会产生性能问题,为了解决该问题,引入了模板解释器。
定义
模板解释器可以理解为将每个字节码的汇编实现都预先定义好,然后将其作为标准模板放入模板表。
模板
由于每个字节码的行为不同,因此将模板做了以下定义
/*templateTable.hpp*/
class Template {
...
int _flags; //标志位,不同位标定该函数具有哪些行为,例如读取字节码后一位,调用运行时函数等
TosState _tos_in; //进入栈顶状态
TosState _tos_out; //输出栈顶状态
generator _gen; //这是一个函数指针,指向的是字节码的具体实现函数
int _arg; //字节码实现函数的输入参数
...
}
举例说明,例如iadd字节码,其定义为将栈顶的2个整型相加,结果推向栈顶,那么其输入栈顶状态为整型,输出栈顶状态为整型,假设字节码生成的汇编的函数名为iop2,参数为枚举值add,那么该模板可以定义为
Template* t;
t._tos_in = itos;
t._tos_out= itos;
t._gen=iop2;
t._arg=add;
除此之外,_flags参数用于说明字节码函数实现时的行为
const int ____ = 0;
const int ubcp = 1 << Template::uses_bcp_bit; //需要使用字节码指针向后读取参数
const int disp = 1 << Template::does_dispatch_bit;//是否会执行跳转操作
const int clvm = 1 << Template::calls_vm_bit;//是否会调运行时函数
const int iswd = 1 << Template::wide_bit;//是否支持宽指令
举例说明bipush字节码
该字节码的定义为将字节码后跟的数字推送至栈顶。假设把整数10推送至栈顶。那么字节码的形式如下
bipush 10
如果此时字节码指针指向bipush字节,那么当执行字节码时则必须向后移动一位实现参数10的读取。
模板表
模板表本质上是一个Template类型的数组。定义如下
/*templateTable.hpp*/
class TemplateTable: AllStatic {
...
static Template _template_table [Bytecodes::number_of_codes];
...
}
模板表是一个静态变量,这意味着在内存中的位置常驻且不会发生动态改变。
模板表的初始化过程使得每个模板的定义都放在模板表中的对应位置
/*templateTable.cpp*/
void TemplateTable::initialize() {
...
// Java spec bytecodes ubcp|disp|clvm|iswd in out generator argument
def(Bytecodes::_nop , ____|____|____|____, vtos, vtos, nop, _);
...
def(Bytecodes::_bipush ,ubcp|____|____|____, vtos, itos, bipush, _);
...
}
这里的def函数的作用是将模板表中的字节码对象取出来,然后通过initialize函数进行属性赋值。
void TemplateTable::def(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(int arg), int arg) {
...
//在模板表中取出对应字节码的对象
Template* t = is_wide ? template_for_wide(code) : template_for(code);
//将传入的参数赋值给该对象
t->initialize(flags, in, out, gen, arg);
}
经过上述步骤,模板表中的所有模板已完成定义。
模板生成
在模板表中将每个字节码定义完毕后,回到前文所述,在转发表中设置每个字节码指令的入口过程,转发表中的字节码对应从模板表中取出的指令模板对象,然后为该模板对象加入各种栈顶状态的入口地址
/*templateTableGenerator.cpp*/
void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) {
...
if (Bytecodes::is_defined(code)) {
Template* t = TemplateTable::template_for(code);
...
set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep);
...
}

在set_short_entry_points过程中实现了个字节码模板的汇编生成
/*templateTableGenerator.cpp*/
void TemplateInterpreterGenerator::set_short_entry_points(Template* t,...){
...
generate_and_dispatch(t);
...
}
void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, ...){
// generate template
t->generate(_masm);//这里_masm为指定平台的汇编器
}
以bipush字节码为例,在模板表中定义bipush字节码实现为bipush函数
def(Bytecodes::_bipush ,ubcp|____|____|____, vtos, itos, bipush, _);
这里Bytecodes::_bipush为bipush字节码的值,其对应的实现为bipush函数。在x86平台的实现如下
/*templateTable_x86.cpp*/
void TemplateTable::bipush() {
transition(vtos, itos);
//把字节码指针后一个字节的值放入rax寄存器
__ load_signed_byte(rax, at_bcp(1));
}

1662

被折叠的 条评论
为什么被折叠?



