Repository navigation
runtime interp stack
ceragon edited this page Jun 6, 2022
·
3 revisions
| 索引 | 大小 | 名称 | 作用 |
|---|---|---|---|
| 0 | 8 | save rax | 保存返回地址 |
| 1 | 8 | save rbp | 保存栈帧的基址 |
| === | = | === | === |
| 1 | 8 | save rbcp(r13) | 保存调用者的 rsp,产生方法调用那一刻时的 rsp |
| 2 | 8 | NULL_WORD | 占位 (last_sp) |
| 3 | 8 | Method* | (Method) 保存方法对象的地址 |
| 4 | 8 | java mirror | 方法所在的java class 对象地址 |
| 5 | 8 | method data | (Method->MethodData) 代码的首地址 |
| 6 | 8 | constant pool cache | 常量池的cache |
| 7 | 8 | locals pointer | 局部变量表的地址 |
| 8 | 8 | codes | 代码地址 |
| 9 | 8 | rsp | 栈底的地址 |
enum {
pc_return_offset = 0,
// All frames
link_offset = 0,
return_addr_offset = 1,
// non-interpreter frames
sender_sp_offset = 2,
// Interpreter frames
interpreter_frame_result_handler_offset = 3, // for native calls only
interpreter_frame_oop_temp_offset = 2, // for native calls only
interpreter_frame_sender_sp_offset = -1,
// outgoing sp before a call to an invoked method
interpreter_frame_last_sp_offset = interpreter_frame_sender_sp_offset - 1,
interpreter_frame_method_offset = interpreter_frame_last_sp_offset - 1,
interpreter_frame_mirror_offset = interpreter_frame_method_offset - 1,
interpreter_frame_mdp_offset = interpreter_frame_mirror_offset - 1,
interpreter_frame_cache_offset = interpreter_frame_mdp_offset - 1,
interpreter_frame_locals_offset = interpreter_frame_cache_offset - 1,
interpreter_frame_bcp_offset = interpreter_frame_locals_offset - 1,
interpreter_frame_initial_sp_offset = interpreter_frame_bcp_offset - 1,
interpreter_frame_monitor_block_top_offset = interpreter_frame_initial_sp_offset,
interpreter_frame_monitor_block_bottom_offset = interpreter_frame_initial_sp_offset,
entry_frame_call_wrapper_offset = 2
};没有列出全部,只是一部分数据结构
class Method : public Metadata {
// 方法的只读数据
ConstMethod* _constMethod;
MethodData* _method_data;
MethodCounters* _method_counters;
AccessFlags _access_flags;
};class ConstMethod : public MetaspaceObj {
ConstantPool* _constants;
u2 _max_stack;
u2 _max_locals;
u2 _size_of_parameters;
};class ConstantPool : public Metadata {
Array<u1>* _tags;
ConstantPoolCache* _cache;
InstanceKlass* _pool_holder;
Array<u2>* _operands;
int _length; // number of elements in the array
};class ConstantPoolCacheEntry {
volatile intx _flags; // flags
};class MethodData : public Metadata {
int _data_size;
// Beginning of the data entries
intptr_t _data[1];
};class InstanceKlass: public Klass {
Annotations* _annotations;
PackageEntry* _package_entry;
Klass* volatile _array_klasses;
ConstantPool* _constants;
};address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
__ pop(rax);
}只会贴出改变栈空间的指令
void TemplateTable::invokespecial(int byte_no) {
prepare_invoke(byte_no, rbx, noreg, // get f1 Method*
rcx); // get receiver also for null check
}| 序号 | 名称 | 作用 |
|---|---|---|
| 0 | rbp | 栈帧基址 |
| -8 | bcp | 发生方法调用的时候,用于存储方法字节码序列中产生调用字节码的首地址,例如 invokeSpecial |
| 0 | rbp | 下一个方法的栈帧基址 |
先追溯一下 _bcp_register 的赋值
void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
int step = 0;
if (!t->does_dispatch()) {
// 计算字节码的长度
step = t->is_wide() ?
Bytecodes::wide_length_for(t->bytecode())
: Bytecodes::length_for(t->bytecode());
}
// 生成字节码对应 native code
t->generate(_masm);
__ dispatch_epilog(tos_out, step);
}
void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) {
dispatch_next(state, step);
}
void InterpreterMacroAssembler::dispatch_next(TosState state, int step, bool generate_poll) {
// _bcp_register:方法中当前执行的字节码首地址
// step: 当前字节码的大小
// _bcp_register: 变为下一个字节码的首地址
increment(_bcp_register, step);
}下面是修改栈数据的地方
void TemplateTable::invokespecial(int byte_no) {
prepare_invoke(byte_no, rbx, noreg, // get f1 Method*
rcx); // get receiver also for null check
}
void TemplateTable::prepare_invoke(int byte_no,
Register method, // linked method (or i-klass)
Register index, // itable index, MethodType, etc.
Register recv, // if caller wants to see it
Register flags // if caller wants to test it
) {
// __ save_bcp();
// _bcp_register: r13
// 将方法中当前字节码的首地址存到栈空间的指定问题
movptr(Address(rbp, frame::interpreter_frame_bcp_offset * wordSize), _bcp_register);
}| 序号 | 名称 | 作用 |
|---|---|---|
| 0 | rbp | 栈帧基址 |
| return address | 返回地址 | |
| 0 | rbp | 下一个方法的栈帧基址 |
void TemplateTable::invokespecial(int byte_no) {
prepare_invoke(byte_no, rbx, noreg, // get f1 Method*
rcx); // get receiver also for null check
}
const int LogBytesPerInt = 2;
const int LogBitsPerByte = 3;
// 5
const int LogBitsPerInt = LogBitsPerByte + LogBytesPerInt;
// 1 << 5 == 32
const int BitsPerInt = 1 << LogBitsPerInt;
enum {
tos_state_bits = 4,
// 32 - 4 = 28
tos_state_shift = BitsPerInt - tos_state_bits,
};
void TemplateTable::prepare_invoke(int byte_no,
Register method, // linked method (or i-klass)
Register index, // itable index, MethodType, etc.
Register recv, // if caller wants to see it
Register flags // if caller wants to test it
) {
if (flags == noreg) flags = rdx;
// 加载常量池中的 flags
load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
// flags 右移 28 位
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
{
// 获取 return_entry_table 的地址
const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
ExternalAddress table(table_addr);
// 把地址加载到 rscratch1 中
__ lea(rscratch1, table)
// flags = [rscratch1 + (flags * Address::times_ptr)]
__ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
}
// push return address
__ push(flags);
}
Constant pool:
#2 = Class #25 // Test
#4 = Methodref #2.#26 // Test.print2:()V
#9 = Utf8 ()V
#21 = Utf8 print2
#25 = Utf8 Test
#26 = NameAndType #21:#9 // print2:()V
invokevirtual #4 // Method print2:()V
void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
Register method,
Register itable_index,
Register flags,
bool is_invokevirtual,
bool is_invokevfinal, /*unused*/
bool is_invokedynamic) {
const Register cache = rcx;
const Register index = rdx;
// 常量池有两个部分组成, cache 和 cacheEntry
// 计算出 flags 所在的偏移
const int flags_offset = in_bytes(ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::flags_offset());
// invokeSpecial 是 u2
size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
// 处理了 cache 的赋值
resolve_cache_and_index(byte_no, cache, index, index_size);
// cache: 常量池缓存的地址
// index: 字节码指令后面的值,例如例子中的 #4。但会在上一步左移2位
// flags: (cache + index*3 + flags_offset) 地址对应的值
// 看不懂变址寻址的结果,姑且认为是常量池里的 flags 吧
__ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
}
void TemplateTable::resolve_cache_and_index(int byte_no,
Register Rcache,
Register index,
size_t index_size) {
__ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
}
void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache,
Register index,
Register bytecode,
int byte_no,
int bcp_offset,
size_t index_size) {
get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size);
}
void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
Register index,
int bcp_offset,
size_t index_size) {
// index = 字节码后面的参数
get_cache_index_at_bcp(index, bcp_offset, index_size);
// rbp: 当前的栈基址
// cache: 常量池缓存的地址
movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
// index: 左移两位
shll(index, 2);
}
void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
int bcp_offset,
size_t index_size) {
if (index_size == sizeof(u2)) {
// invokeSpecial
// 结合上下文,bcp_offset 是 1
// index = (_bcp_register + 1) 地址里的值
// 如上面的示例中, index=#4
load_unsigned_short(index, Address(_bcp_register, bcp_offset));
}
}address* TemplateInterpreter::invoke_return_entry_table_for(Bytecodes::Code code) {
switch (code) {
case Bytecodes::_invokespecial:
return Interpreter::invoke_return_entry_table();
}
}
class TemplateInterpreter: public AbstractInterpreter {
static address _invoke_return_entry[number_of_return_addrs]; // for invokestatic, invokespecial, invokevirtual return entries
static address* invoke_return_entry_table() {
return _invoke_return_entry;
}
};address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) {
address entry = __ pc();
__ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
__ restore_bcp();
__ restore_locals();
const Register cache = rbx;
const Register index = rcx;
__ get_cache_and_index_at_bcp(cache, index, 1, index_size);
const Register flags = cache;
__ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
__ andl(flags, ConstantPoolCacheEntry::parameter_size_mask);
__ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale()));
__ dispatch_next(state, step);
return entry;
}