现在我们知道了模板解释器其实是由一堆例程构成的,但是,字节码的例程的呢?看看上面TemplateInterpreter的类定义,有个static DispatchTable _active_table;,它就是我们要找的东西了。具体来说templateInterpreterGenerator会调用TemplateInterpreterGenerator::set_entry_points()为每个字节码设置例程,该例程通过templateTable::template_for()获得。同样,这些代码需要关心cpu架构,所以自己每个字节码的例程也是由hotspot\src\cpu\x86\vm\templateTable_x86.cpp+templateTable共同完成的。
字节码太多了,这里也随便举个例子,考虑istore,它负责将栈顶数据出栈并存放到当前方法的局部变量表,实现如下:
合情合理的实现
等等,当使用-XX:+PrintInterpreter查看istore的合情合理的例程时却得到了一大堆汇编:
---------------------------------------------------------------------- istore 54 istore [0x00000192d1972ba0, 0x00000192d1972c00] 96 bytes 0x00000192d1972ba0: mov (%rsp),%eax 0x00000192d1972ba3: add $0x8,%rsp 0x00000192d1972ba7: movzbl 0x1(%r13),%ebx 0x00000192d1972bac: neg %rbx 0x00000192d1972baf: mov %eax,(%r14,%rbx,8) 0x00000192d1972bb3: movzbl 0x2(%r13),%ebx 0x00000192d1972bb8: add $0x2,%r13 0x00000192d1972bbc: movabs $0x7fffd56e0fa0,%r10 0x00000192d1972bc6: jmpq *(%r10,%rbx,8) 0x00000192d1972bca: mov (%rsp),%eax 0x00000192d1972bcd: add $0x8,%rsp 0x00000192d1972bd1: movzwl 0x2(%r13),%ebx 0x00000192d1972bd6: bswap %ebx 0x00000192d1972bd8: shr $0x10,%ebx 0x00000192d1972bdb: neg %rbx 0x00000192d1972bde: mov %eax,(%r14,%rbx,8) 0x00000192d1972be2: movzbl 0x4(%r13),%ebx 0x00000192d1972be7: add $0x4,%r13 0x00000192d1972beb: movabs $0x7fffd56e0fa0,%r10 0x00000192d1972bf5: jmpq *(%r10,%rbx,8) 0x00000192d1972bf9: nopl 0x0(%rax)虽然勉强能看出mov %eax,(%r14,%rbx,8)对应__ movl(iaddress(n), rax);,但是多出来的代码怎么回事。
要回答这个问题,需要点其他知识。
之前提到
templateInterpreterGenerator会调用TemplateInterpreterGenerator::set_entry_points()为每个字节码设置例程
可以从set_entry_points出发看看它为istore做了什么特殊的事情:
... // 指令是否存在 if (Bytecodes::is_defined(code)) { Template* t = TemplateTable::template_for(code); assert(t->is_valid(), "just checking"); set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); } // 指令是否可以扩宽,即wide if (Bytecodes::wide_is_defined(code)) { Template* t = TemplateTable::template_for_wide(code); assert(t->is_valid(), "just checking"); set_wide_entry_point(t, wep); } ... }中间有一句话:
Template* t = TemplateTable::template_for(code);从模板表中的查找Bytecodes::Code常量得到的是一个Template,Template描述了一个指定的字节码对应的代码的一些属性
// A Template describes the properties of a code template for a given bytecode
// and provides a generator to generate the code template.
然后找到istore对应的模板定义:
//hotspot\src\share\vm\interpreter\templateTable.cpp void TemplateTable::initialize() { ... // interpr. templates // Java spec bytecodes ubcp|disp|clvm|iswd in out generator argument def(Bytecodes::_istore , ubcp|____|clvm|____, itos, vtos, istore , _ ); def(Bytecodes::_lstore , ubcp|____|____|____, ltos, vtos, lstore , _ ); def(Bytecodes::_fstore , ubcp|____|____|____, ftos, vtos, fstore , _ ); def(Bytecodes::_dstore , ubcp|____|____|____, dtos, vtos, dstore , _ ); def(Bytecodes::_astore , ubcp|____|clvm|____, vtos, vtos, astore , _ ); ... // wide Java spec bytecodes def(Bytecodes::_istore , ubcp|____|____|iswd, vtos, vtos, wide_istore , _ ); def(Bytecodes::_lstore , ubcp|____|____|iswd, vtos, vtos, wide_lstore , _ ); def(Bytecodes::_fstore , ubcp|____|____|iswd, vtos, vtos, wide_fstore , _ ); def(Bytecodes::_dstore , ubcp|____|____|iswd, vtos, vtos, wide_dstore , _ ); def(Bytecodes::_astore , ubcp|____|____|iswd, vtos, vtos, wide_astore , _ ); def(Bytecodes::_iinc , ubcp|____|____|iswd, vtos, vtos, wide_iinc , _ ); def(Bytecodes::_ret , ubcp|disp|____|iswd, vtos, vtos, wide_ret , _ ); def(Bytecodes::_breakpoint , ubcp|disp|clvm|____, vtos, vtos, _breakpoint , _ ); ... }