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

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

hotspot解释器模块(hotspot\src\share\vm\interpreter)有两个实现:基于C++的解释器和基于汇编的模板解释器。hotspot默认使用比较快的模板解释器。
其中

C++解释器 = bytecodeInterpreter* + cppInterpreter*

模板解释器 = templateTable* + templateInterpreter*

它们前者负责字节码的解释,后者负责解释器的运行时,共同完成解释功能。这里我们只关注模板解释器。

模板解释器又分为三个组成部分:

templateInterpreterGenerator 解释器生成器

templateTable 字节码实现

templateInterpreter 解释器
可能看起来很奇怪,为什么有一个解释器生成器和字节码实现。进入解释器实现:

class TemplateInterpreter: public AbstractInterpreter { friend class VMStructs; friend class InterpreterMacroAssembler; friend class TemplateInterpreterGenerator; friend class TemplateTable; friend class CodeCacheExtensions; // friend class Interpreter; public: enum MoreConstants { number_of_return_entries = number_of_states, // number of return entry points number_of_deopt_entries = number_of_states, // number of deoptimization entry points number_of_return_addrs = number_of_states // number of return addresses }; protected: static address _throw_ArrayIndexOutOfBoundsException_entry; static address _throw_ArrayStoreException_entry; static address _throw_ArithmeticException_entry; static address _throw_ClassCastException_entry; static address _throw_NullPointerException_entry; static address _throw_exception_entry; static address _throw_StackOverflowError_entry; static address _remove_activation_entry; // continuation address if an exception is not handled by current frame #ifdef HOTSWAP static address _remove_activation_preserving_args_entry; // continuation address when current frame is being popped #endif // HOTSWAP #ifndef PRODUCT static EntryPoint _trace_code; #endif // !PRODUCT static EntryPoint _return_entry[number_of_return_entries]; // entry points to return to from a call static EntryPoint _earlyret_entry; // entry point to return early from a call static EntryPoint _deopt_entry[number_of_deopt_entries]; // entry points to return to from a deoptimization static EntryPoint _continuation_entry; static EntryPoint _safept_entry; static address _invoke_return_entry[number_of_return_addrs]; // for invokestatic, invokespecial, invokevirtual return entries static address _invokeinterface_return_entry[number_of_return_addrs]; // for invokeinterface return entries static address _invokedynamic_return_entry[number_of_return_addrs]; // for invokedynamic return entries static DispatchTable _active_table; // the active dispatch table (used by the interpreter for dispatch) static DispatchTable _normal_table; // the normal dispatch table (used to set the active table in normal mode) static DispatchTable _safept_table; // the safepoint dispatch table (used to set the active table for safepoints) static address _wentry_point[DispatchTable::length]; // wide instructions only (vtos tosca always) public: ... static int InterpreterCodeSize; };

里面很多address变量,EntryPoint是一个address数组,DispatchTable也是。
模板解释器就是由一系列例程(routine)组成的,即address变量,它们每个都表示一个例程的入口地址,比如异常处理例程,invoke指令例程,用于gc的safepoint例程...
举个形象的例子,我们都知道字节码文件长这样:

public void f(); 0: aload_0 1: invokespecial #5 // Method A.f:()V 4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 7: ldc #6 // String ff 9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 12: return

如果要让我们写解释器,可能基本上就是一个循环里面switch,根据不同opcode派发到不同例程,例程的代码都是一样的模板代码,对aload_0的处理永远是取局部变量槽0的数据放到栈顶,那么完全可以在switch派发字节码前准备好这些模板代码,templateInterpreterGenerator就是做的这件事,它的generate_all()函数初始化了所有的例程:

void TemplateInterpreterGenerator::generate_all() { // 设置slow_signature_handler例程 { CodeletMark cm(_masm, "slow signature handler"); AbstractInterpreter::_slow_signature_handler = generate_slow_signature_handler(); } // 设置error_exit例程 { CodeletMark cm(_masm, "error exits"); _unimplemented_bytecode = generate_error_exit("unimplemented bytecode"); _illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified"); } ...... }

另外,既然已经涉及到机器码了,单独的templateInterpreterGenerator显然是不能完成这件事的,它还需要配合
hotspot\src\cpu\x86\vm\templateInterpreterGenerator_x86.cpp&&hotspot\src\cpu\x86\vm\templateInterpreterGenerator_x86_64.cpp一起做事(我的机器是x86+windows)。

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

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