[inside hotspot] 汇编模板解释器(Template Interpreter)和字节码执行 (3)

现在我们知道了模板解释器其实是由一堆例程构成的,但是,字节码的例程的呢?看看上面TemplateInterpreter的类定义,有个static DispatchTable _active_table;,它就是我们要找的东西了。具体来说templateInterpreterGenerator会调用TemplateInterpreterGenerator::set_entry_points()为每个字节码设置例程,该例程通过templateTable::template_for()获得。同样,这些代码需要关心cpu架构,所以自己每个字节码的例程也是由hotspot\src\cpu\x86\vm\templateTable_x86.cpp+templateTable共同完成的。
字节码太多了,这里也随便举个例子,考虑istore,它负责将栈顶数据出栈并存放到当前方法的局部变量表,实现如下:

void TemplateTable::istore() { transition(itos, vtos); locals_index(rbx); __ movl(iaddress(rbx), rax); }

合情合理的实现

等等,当使用-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.

// hotspot\src\share\vm\utilities\globalDefinitions.hpp // TosState用来描述一个字节码或者方法执行前后的状态。 enum TosState { // describes the tos cache contents btos = 0, // byte, bool tos cached ztos = 1, // byte, bool tos cached ctos = 2, // char tos cached stos = 3, // short tos cached itos = 4, // int tos cached ltos = 5, // long tos cached ftos = 6, // float tos cached dtos = 7, // double tos cached atos = 8, // object cached vtos = 9, // tos not cached number_of_states, ilgl // illegal state: should not occur }; // hotspot\src\share\vm\interpreter\templateTable.hpp class Template VALUE_OBJ_CLASS_SPEC { private: enum Flags { uses_bcp_bit, // 是否需要字节码指针(bcp)? does_dispatch_bit, // 是否需要dispatch? calls_vm_bit, // 是否调用了虚拟机方法? wide_bit // 能否扩宽,即加wide }; typedef void (*generator)(int arg); // 字节码代码生成器,其实是一个函数指针 int _flags; // 就是↑描述的flag TosState _tos_in; // 执行字节码前的栈顶缓存状态 TosState _tos_out; // 执行字节码的栈顶缓存状态 generator _gen; // 字节码代码生成器 int _arg; // 字节码代码生成器参数

然后找到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 , _ ); ... }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjpxz.html