看jvm源码的时候怎么也看不懂,来回看了几次了就是关于iload 6 指令的解析
def(Bytecodes::_lload , ubcp|____|____|____, vtos, ltos, lload , _ );
看重载的def函数
const char _ = ' '; const int ____ = 0;
其中的_ 是上面的定义
void TemplateTable::def(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(), char filler) { assert(filler == ' ', "just checkin'"); def(code, flags, in, out, (Template::generator)gen, 0); } //下面对应的有参函数 对应上面的无参函数 void TemplateTable::def(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(int arg), int arg) { // should factor out these constants 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; // determine which table to use bool is_wide = (flags & iswd) != 0; // make sure that wide instructions have a vtos entry point // (since they are executed extremely rarely, it doesn't pay out to have an // extra set of 5 dispatch tables for the wide instructions - for simplicity // they all go with one table) assert(in == vtos || !is_wide, "wide instructions have vtos entry point only"); Template* t = is_wide ? template_for_wide(code) : template_for(code); // setup entry t->initialize(flags, in, out, gen, arg); assert(t->bytecode() == code, "just checkin'"); }
上面没有什么能明白调用了无参的gen()函数,那么就是
void TemplateTable::iload() { transition(vtos, itos); if (RewriteFrequentPairs) { Label rewrite, done; // get next byte __ load_unsigned_byte(rbx, at_bcp(Bytecodes::length_for(Bytecodes::_iload))); // if _iload, wait to rewrite to iload2. We only want to rewrite the // last two iloads in a pair. Comparing against fast_iload means that // the next bytecode is neither an iload or a caload, and therefore // an iload pair. __ cmpl(rbx, Bytecodes::_iload); __ jcc(Assembler::equal, done); __ cmpl(rbx, Bytecodes::_fast_iload); __ movl(rcx, Bytecodes::_fast_iload2); __ jccb(Assembler::equal, rewrite); // if _caload, rewrite to fast_icaload __ cmpl(rbx, Bytecodes::_caload); __ movl(rcx, Bytecodes::_fast_icaload); __ jccb(Assembler::equal, rewrite); // rewrite so iload doesn't check again. __ movl(rcx, Bytecodes::_fast_iload); // rewrite // rcx: fast bytecode __ bind(rewrite); patch_bytecode(Bytecodes::_iload, rcx, rbx, false); __ bind(done); } //以上忽略 // Get the local value into tos locals_index(rbx); __ movl(rax, iaddress(rbx)); }
接下来
void TemplateTable::locals_index(Register reg, int offset) { __ load_unsigned_byte(reg, at_bcp(offset)); __ negptr(reg); }
我开始找 locals_index() 函数,只有这个两个参数的,以为有重载,结果没有,然后查资料说是有,可以省略参数,就将0作为默认参数,就不需要写这个0了
locals_index(rbx,0)
但是逻辑不符合,应该是 locals_index(rbx,1)才对
于是又发现在hpp文件中有一个定义
static void locals_index(Register reg, int offset = 1);
莫非这个意思是设置默认值,然后省略了 1 ?
在本地做了实验
main.hpp #ifndef UNTITLED2_MAIN_H #define UNTITLED2_MAIN_H #endif //UNTITLED2_MAIN_H static void locals_index(int reg, int offset = 1); main.cpp #include<stdio.h> #include "main.h" int main(int argc, char* argv[]){ locals_index(1); return 0; } void locals_index(int reg, int offset){ printf("c=%d ",reg+offset); } //控制台打印 C:UsersmetoCLionProjectsuntitled2cmake-build-debuguntitled2.exe c=2 Process finished with exit code 0
果然是这个样子,说明了c++有默认值的用法
小c佳,你这样子不好,让我好一顿找