揭秘OpenJDK 17字节码解释引擎:模板解释器深度解析
Java字节码的执行是JVM的核心能力,而OpenJDK 17的模板解释器(Template Interpreter)则是高效解释执行的关键。本文将深入剖析其工作原理,带您一窥Java程序在JVM中的执行奥秘。
一、模板解释器的核心设计
模板解释器通过预编译机器码模板代替传统的switch-case解释循环,其核心是模板表初始化过程:
cpp
// 字节码模板定义示例 def(Bytecodes::_iadd, ____|____|____|____, itos, itos, iop2, add); def(Bytecodes::_new, ubcp|____|clvm|____, vtos, atos, _new, _);
每个模板定义包含:
-
字节码标识(如
_iadd
) -
标志位(是否使用常量池/需要分派等)
-
输入/输出栈顶状态(
itos
整型输入输出) -
生成器函数(
iop2
执行整数运算) -
附加参数(
add
指定加法操作)
二、字节码执行四步流程
步骤1:入口点绑定
cpp
void set_entry_points(Bytecodes::Code code) {Template* t = TemplateTable::template_for(code);set_short_entry_points(t, bep, cep, sep...); Interpreter::_normal_table.set_entry(code, entry); }
根据字节码类型绑定预生成的机器码入口,后续执行直接跳转无需解析。
步骤2:栈帧初始化
方法调用时构建完整的调用环境:
cpp
void generate_normal_entry(bool synchronized) {// 1. 计算参数和局部变量大小__ load_unsigned_short(rcx, size_of_parameters); // 2. 栈溢出检查generate_stack_overflow_check(); // 3. 分配局部变量空间__ lea(rlocals, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize));// 4. 构建固定帧结构generate_fixed_frame(false); }
步骤3:字节码分派
通过高效分派机制跳转到目标字节码处理:
cpp
void dispatch_next(TosState state, int step) {load_unsigned_byte(rbx, Address(_bcp_register, step)); // 加载下一字节码increment(_bcp_register, step); // 更新字节码指针dispatch_base(state, Interpreter::dispatch_table(state)); }
步骤4:模板执行
针对具体字节码执行预编译的机器码:
cpp
void generate_and_dispatch(Template* t) {t->generate(_masm); // 生成当前字节码的机器码__ dispatch_epilog(tos_out, step); // 分派到下一字节码 }
三、关键优化技术
-
栈顶状态敏感优化
cpp
switch (t->tos_in()) {case atos: __ pop(atos); generate_and_dispatch(t); break;case itos: __ pop(itos); generate_and_dispatch(t); break;//... }
根据输入/输出类型生成特化代码,避免冗余类型转换。
-
快速路径指令
cpp
def(Bytecodes::_fast_igetfield, ubcp|____|____|____, atos, itos, fast_accessfield, itos);
对字段访问等高频操作提供快速路径,绕过常规查找流程。
-
调用计数器
cpp
Label invocation_counter_overflow; generate_counter_incr(&invocation_counter_overflow);
统计方法调用次数,触发JIT编译的黄金标准。
-
安全点轮询
cpp
if (generate_poll) {testb(Address(thread, JavaThread::polling_word_offset()), poll_bit());jcc(Assembler::notZero, handle_safepoint); }
在分派点插入安全点检查,实现GC等操作的协同。
四、性能对比:模板解释器 vs 传统解释器
特性 | 模板解释器 | 传统解释器 |
---|---|---|
执行机制 | 预编译机器码模板 | switch-case循环 |
分派开销 | 1次内存跳转 | 多次条件判断 |
类型转换 | 生成特化代码 | 运行时动态判断 |
编译开销 | 启动时预生成 | 无 |
平均性能提升 | 2-5倍 | 基准 |
五、技术演进思考
-
分层编译的基石:模板解释器作为"第0层编译器",为C1/C2编译器提供性能分析数据
-
与AOT的协同:预编译机制为GraalVM原生镜像提供技术铺垫
-
未来优化方向:
-
SIMD指令在模板中的利用
-
基于AI的模板自动优化
-
异构计算设备支持
-
结语
OpenJDK 17的模板解释器通过预编译+直接分派的核心设计,在解释执行和编译执行间架起高效桥梁。这种"用空间换时间"的策略,使Java在启动速度和长期运行性能间取得精妙平衡,奠定了现代JVM高效执行的基础。随着Java虚拟线程等新技术的发展,解释器作为执行引擎基石的角色将更加重要。
##源码
void TemplateTable::initialize() {
#ifdef ASSERTstatic bool is_initialized = false;assert(!is_initialized, "must only initialize once");is_initialized = true;
#endif// For better readabilityconst char _ = ' ';const int ____ = 0;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;// interpr. templates// Java spec bytecodes ubcp|disp|clvm|iswd in out generator argumentdef(Bytecodes::_nop , ____|____|____|____, vtos, vtos, nop , _ );def(Bytecodes::_aconst_null , ____|____|____|____, vtos, atos, aconst_null , _ );def(Bytecodes::_iconst_m1 , ____|____|____|____, vtos, itos, iconst , -1 );def(Bytecodes::_iconst_0 , ____|____|____|____, vtos, itos, iconst , 0 );def(Bytecodes::_iconst_1 , ____|____|____|____, vtos, itos, iconst , 1 );def(Bytecodes::_iconst_2 , ____|____|____|____, vtos, itos, iconst , 2 );def(Bytecodes::_iconst_3 , ____|____|____|____, vtos, itos, iconst , 3 );def(Bytecodes::_iconst_4 , ____|____|____|____, vtos, itos, iconst , 4 );def(Bytecodes::_iconst_5 , ____|____|____|____, vtos, itos, iconst , 5 );def(Bytecodes::_lconst_0 , ____|____|____|____, vtos, ltos, lconst , 0 );def(Bytecodes::_lconst_1 , ____|____|____|____, vtos, ltos, lconst , 1 );def(Bytecodes::_fconst_0 , ____|____|____|____, vtos, ftos, fconst , 0 );def(Bytecodes::_fconst_1 , ____|____|____|____, vtos, ftos, fconst , 1 );def(Bytecodes::_fconst_2 , ____|____|____|____, vtos, ftos, fconst , 2 );def(Bytecodes::_dconst_0 , ____|____|____|____, vtos, dtos, dconst , 0 );def(Bytecodes::_dconst_1 , ____|____|____|____, vtos, dtos, dconst , 1 );def(Bytecodes::_bipush , ubcp|____|____|____, vtos, itos, bipush , _ );def(Bytecodes::_sipush , ubcp|____|____|____, vtos, itos, sipush , _ );def(Bytecodes::_ldc , ubcp|____|clvm|____, vtos, vtos, ldc , false );def(Bytecodes::_ldc_w , ubcp|____|clvm|____, vtos, vtos, ldc , true );def(Bytecodes::_ldc2_w , ubcp|____|clvm|____, vtos, vtos, ldc2_w , _ );def(Bytecodes::_iload , ubcp|____|clvm|____, vtos, itos, iload , _ );def(Bytecodes::_lload , ubcp|____|____|____, vtos, ltos, lload , _ );def(Bytecodes::_fload , ubcp|____|____|____, vtos, ftos, fload , _ );def(Bytecodes::_dload , ubcp|____|____|____, vtos, dtos, dload , _ );def(Bytecodes::_aload , ubcp|____|clvm|____, vtos, atos, aload , _ );def(Bytecodes::_iload_0 , ____|____|____|____, vtos, itos, iload , 0 );def(Bytecodes::_iload_1 , ____|____|____|____, vtos, itos, iload , 1 );def(Bytecodes::_iload_2 , ____|____|____|____, vtos, itos, iload , 2 );def(Bytecodes::_iload_3 , ____|____|____|____, vtos, itos, iload , 3 );def(Bytecodes::_lload_0 , ____|____|____|____, vtos, ltos, lload , 0 );def(Bytecodes::_lload_1 , ____|____|____|____, vtos, ltos, lload , 1 );def(Bytecodes::_lload_2 , ____|____|____|____, vtos, ltos, lload , 2 );def(Bytecodes::_lload_3 , ____|____|____|____, vtos, ltos, lload , 3 );def(Bytecodes::_fload_0 , ____|____|____|____, vtos, ftos, fload , 0 );def(Bytecodes::_fload_1 , ____|____|____|____, vtos, ftos, fload , 1 );def(Bytecodes::_fload_2 , ____|____|____|____, vtos, ftos, fload , 2 );def(Bytecodes::_fload_3 , ____|____|____|____, vtos, ftos, fload , 3 );def(Bytecodes::_dload_0 , ____|____|____|____, vtos, dtos, dload , 0 );def(Bytecodes::_dload_1 , ____|____|____|____, vtos, dtos, dload , 1 );def(Bytecodes::_dload_2 , ____|____|____|____, vtos, dtos, dload , 2 );def(Bytecodes::_dload_3 , ____|____|____|____, vtos, dtos, dload , 3 );def(Bytecodes::_aload_0 , ubcp|____|clvm|____, vtos, atos, aload_0 , _ );def(Bytecodes::_aload_1 , ____|____|____|____, vtos, atos, aload , 1 );def(Bytecodes::_aload_2 , ____|____|____|____, vtos, atos, aload , 2 );def(Bytecodes::_aload_3 , ____|____|____|____, vtos, atos, aload , 3 );def(Bytecodes::_iaload , ____|____|____|____, itos, itos, iaload , _ );def(Bytecodes::_laload , ____|____|____|____, itos, ltos, laload , _ );def(Bytecodes::_faload , ____|____|____|____, itos, ftos, faload , _ );def(Bytecodes::_daload , ____|____|____|____, itos, dtos, daload , _ );def(Bytecodes::_aaload , ____|____|____|____, itos, atos, aaload , _ );def(Bytecodes::_baload , ____|____|____|____, itos, itos, baload , _ );def(Bytecodes::_caload , ____|____|____|____, itos, itos, caload , _ );def(Bytecodes::_saload , ____|____|____|____, itos, itos, saload , _ );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 , _ );def(Bytecodes::_istore_0 , ____|____|____|____, itos, vtos, istore , 0 );def(Bytecodes::_istore_1 , ____|____|____|____, itos, vtos, istore , 1 );def(Bytecodes::_istore_2 , ____|____|____|____, itos, vtos, istore , 2 );def(Bytecodes::_istore_3 , ____|____|____|____, itos, vtos, istore , 3 );def(Bytecodes::_lstore_0 , ____|____|____|____, ltos, vtos, lstore , 0 );def(Bytecodes::_lstore_1 , ____|____|____|____, ltos, vtos, lstore , 1 );def(Bytecodes::_lstore_2 , ____|____|____|____, ltos, vtos, lstore , 2 );def(Bytecodes::_lstore_3 , ____|____|____|____, ltos, vtos, lstore , 3 );def(Bytecodes::_fstore_0 , ____|____|____|____, ftos, vtos, fstore , 0 );def(Bytecodes::_fstore_1 , ____|____|____|____, ftos, vtos, fstore , 1 );def(Bytecodes::_fstore_2 , ____|____|____|____, ftos, vtos, fstore , 2 );def(Bytecodes::_fstore_3 , ____|____|____|____, ftos, vtos, fstore , 3 );def(Bytecodes::_dstore_0 , ____|____|____|____, dtos, vtos, dstore , 0 );def(Bytecodes::_dstore_1 , ____|____|____|____, dtos, vtos, dstore , 1 );def(Bytecodes::_dstore_2 , ____|____|____|____, dtos, vtos, dstore , 2 );def(Bytecodes::_dstore_3 , ____|____|____|____, dtos, vtos, dstore , 3 );def(Bytecodes::_astore_0 , ____|____|____|____, vtos, vtos, astore , 0 );def(Bytecodes::_astore_1 , ____|____|____|____, vtos, vtos, astore , 1 );def(Bytecodes::_astore_2 , ____|____|____|____, vtos, vtos, astore , 2 );def(Bytecodes::_astore_3 , ____|____|____|____, vtos, vtos, astore , 3 );def(Bytecodes::_iastore , ____|____|____|____, itos, vtos, iastore , _ );def(Bytecodes::_lastore , ____|____|____|____, ltos, vtos, lastore , _ );def(Bytecodes::_fastore , ____|____|____|____, ftos, vtos, fastore , _ );def(Bytecodes::_dastore , ____|____|____|____, dtos, vtos, dastore , _ );def(Bytecodes::_aastore , ____|____|clvm|____, vtos, vtos, aastore , _ );def(Bytecodes::_bastore , ____|____|____|____, itos, vtos, bastore , _ );def(Bytecodes::_castore , ____|____|____|____, itos, vtos, castore , _ );def(Bytecodes::_sastore , ____|____|____|____, itos, vtos, sastore , _ );def(Bytecodes::_pop , ____|____|____|____, vtos, vtos, pop , _ );def(Bytecodes::_pop2 , ____|____|____|____, vtos, vtos, pop2 , _ );def(Bytecodes::_dup , ____|____|____|____, vtos, vtos, dup , _ );def(Bytecodes::_dup_x1 , ____|____|____|____, vtos, vtos, dup_x1 , _ );def(Bytecodes::_dup_x2 , ____|____|____|____, vtos, vtos, dup_x2 , _ );def(Bytecodes::_dup2 , ____|____|____|____, vtos, vtos, dup2 , _ );def(Bytecodes::_dup2_x1 , ____|____|____|____, vtos, vtos, dup2_x1 , _ );def(Bytecodes::_dup2_x2 , ____|____|____|____, vtos, vtos, dup2_x2 , _ );def(Bytecodes::_swap , ____|____|____|____, vtos, vtos, swap , _ );def(Bytecodes::_iadd , ____|____|____|____, itos, itos, iop2 , add );def(Bytecodes::_ladd , ____|____|____|____, ltos, ltos, lop2 , add );def(Bytecodes::_fadd , ____|____|____|____, ftos, ftos, fop2 , add );def(Bytecodes::_dadd , ____|____|____|____, dtos, dtos, dop2 , add );def(Bytecodes::_isub , ____|____|____|____, itos, itos, iop2 , sub );def(Bytecodes::_lsub , ____|____|____|____, ltos, ltos, lop2 , sub );def(Bytecodes::_fsub , ____|____|____|____, ftos, ftos, fop2 , sub );def(Bytecodes::_dsub , ____|____|____|____, dtos, dtos, dop2 , sub );def(Bytecodes::_imul , ____|____|____|____, itos, itos, iop2 , mul );def(Bytecodes::_lmul , ____|____|____|____, ltos, ltos, lmul , _ );def(Bytecodes::_fmul , ____|____|____|____, ftos, ftos, fop2 , mul );def(Bytecodes::_dmul , ____|____|____|____, dtos, dtos, dop2 , mul );def(Bytecodes::_idiv , ____|____|____|____, itos, itos, idiv , _ );def(Bytecodes::_ldiv , ____|____|____|____, ltos, ltos, ldiv , _ );def(Bytecodes::_fdiv , ____|____|____|____, ftos, ftos, fop2 , div );def(Bytecodes::_ddiv , ____|____|____|____, dtos, dtos, dop2 , div );def(Bytecodes::_irem , ____|____|____|____, itos, itos, irem , _ );def(Bytecodes::_lrem , ____|____|____|____, ltos, ltos, lrem , _ );def(Bytecodes::_frem , ____|____|____|____, ftos, ftos, fop2 , rem );def(Bytecodes::_drem , ____|____|____|____, dtos, dtos, dop2 , rem );def(Bytecodes::_ineg , ____|____|____|____, itos, itos, ineg , _ );def(Bytecodes::_lneg , ____|____|____|____, ltos, ltos, lneg , _ );def(Bytecodes::_fneg , ____|____|____|____, ftos, ftos, fneg , _ );def(Bytecodes::_dneg , ____|____|____|____, dtos, dtos, dneg , _ );def(Bytecodes::_ishl , ____|____|____|____, itos, itos, iop2 , shl );def(Bytecodes::_lshl , ____|____|____|____, itos, ltos, lshl , _ );def(Bytecodes::_ishr , ____|____|____|____, itos, itos, iop2 , shr );def(Bytecodes::_lshr , ____|____|____|____, itos, ltos, lshr , _ );def(Bytecodes::_iushr , ____|____|____|____, itos, itos, iop2 , ushr );def(Bytecodes::_lushr , ____|____|____|____, itos, ltos, lushr , _ );def(Bytecodes::_iand , ____|____|____|____, itos, itos, iop2 , _and );def(Bytecodes::_land , ____|____|____|____, ltos, ltos, lop2 , _and );def(Bytecodes::_ior , ____|____|____|____, itos, itos, iop2 , _or );def(Bytecodes::_lor , ____|____|____|____, ltos, ltos, lop2 , _or );def(Bytecodes::_ixor , ____|____|____|____, itos, itos, iop2 , _xor );def(Bytecodes::_lxor , ____|____|____|____, ltos, ltos, lop2 , _xor );def(Bytecodes::_iinc , ubcp|____|clvm|____, vtos, vtos, iinc , _ );def(Bytecodes::_i2l , ____|____|____|____, itos, ltos, convert , _ );def(Bytecodes::_i2f , ____|____|____|____, itos, ftos, convert , _ );def(Bytecodes::_i2d , ____|____|____|____, itos, dtos, convert , _ );def(Bytecodes::_l2i , ____|____|____|____, ltos, itos, convert , _ );def(Bytecodes::_l2f , ____|____|____|____, ltos, ftos, convert , _ );def(Bytecodes::_l2d , ____|____|____|____, ltos, dtos, convert , _ );def(Bytecodes::_f2i , ____|____|____|____, ftos, itos, convert , _ );def(Bytecodes::_f2l , ____|____|____|____, ftos, ltos, convert , _ );def(Bytecodes::_f2d , ____|____|____|____, ftos, dtos, convert , _ );def(Bytecodes::_d2i , ____|____|____|____, dtos, itos, convert , _ );def(Bytecodes::_d2l , ____|____|____|____, dtos, ltos, convert , _ );def(Bytecodes::_d2f , ____|____|____|____, dtos, ftos, convert , _ );def(Bytecodes::_i2b , ____|____|____|____, itos, itos, convert , _ );def(Bytecodes::_i2c , ____|____|____|____, itos, itos, convert , _ );def(Bytecodes::_i2s , ____|____|____|____, itos, itos, convert , _ );def(Bytecodes::_lcmp , ____|____|____|____, ltos, itos, lcmp , _ );def(Bytecodes::_fcmpl , ____|____|____|____, ftos, itos, float_cmp , -1 );def(Bytecodes::_fcmpg , ____|____|____|____, ftos, itos, float_cmp , 1 );def(Bytecodes::_dcmpl , ____|____|____|____, dtos, itos, double_cmp , -1 );def(Bytecodes::_dcmpg , ____|____|____|____, dtos, itos, double_cmp , 1 );def(Bytecodes::_ifeq , ubcp|____|clvm|____, itos, vtos, if_0cmp , equal );def(Bytecodes::_ifne , ubcp|____|clvm|____, itos, vtos, if_0cmp , not_equal );def(Bytecodes::_iflt , ubcp|____|clvm|____, itos, vtos, if_0cmp , less );def(Bytecodes::_ifge , ubcp|____|clvm|____, itos, vtos, if_0cmp , greater_equal);def(Bytecodes::_ifgt , ubcp|____|clvm|____, itos, vtos, if_0cmp , greater );def(Bytecodes::_ifle , ubcp|____|clvm|____, itos, vtos, if_0cmp , less_equal );def(Bytecodes::_if_icmpeq , ubcp|____|clvm|____, itos, vtos, if_icmp , equal );def(Bytecodes::_if_icmpne , ubcp|____|clvm|____, itos, vtos, if_icmp , not_equal );def(Bytecodes::_if_icmplt , ubcp|____|clvm|____, itos, vtos, if_icmp , less );def(Bytecodes::_if_icmpge , ubcp|____|clvm|____, itos, vtos, if_icmp , greater_equal);def(Bytecodes::_if_icmpgt , ubcp|____|clvm|____, itos, vtos, if_icmp , greater );def(Bytecodes::_if_icmple , ubcp|____|clvm|____, itos, vtos, if_icmp , less_equal );def(Bytecodes::_if_acmpeq , ubcp|____|clvm|____, atos, vtos, if_acmp , equal );def(Bytecodes::_if_acmpne , ubcp|____|clvm|____, atos, vtos, if_acmp , not_equal );def(Bytecodes::_goto , ubcp|disp|clvm|____, vtos, vtos, _goto , _ );def(Bytecodes::_jsr , ubcp|disp|____|____, vtos, vtos, jsr , _ ); // result is not an oop, so do not transition to atosdef(Bytecodes::_ret , ubcp|disp|____|____, vtos, vtos, ret , _ );def(Bytecodes::_tableswitch , ubcp|disp|____|____, itos, vtos, tableswitch , _ );def(Bytecodes::_lookupswitch , ubcp|disp|____|____, itos, itos, lookupswitch , _ );def(Bytecodes::_ireturn , ____|disp|clvm|____, itos, itos, _return , itos );def(Bytecodes::_lreturn , ____|disp|clvm|____, ltos, ltos, _return , ltos );def(Bytecodes::_freturn , ____|disp|clvm|____, ftos, ftos, _return , ftos );def(Bytecodes::_dreturn , ____|disp|clvm|____, dtos, dtos, _return , dtos );def(Bytecodes::_areturn , ____|disp|clvm|____, atos, atos, _return , atos );def(Bytecodes::_return , ____|disp|clvm|____, vtos, vtos, _return , vtos );def(Bytecodes::_getstatic , ubcp|____|clvm|____, vtos, vtos, getstatic , f1_byte );def(Bytecodes::_putstatic , ubcp|____|clvm|____, vtos, vtos, putstatic , f2_byte );def(Bytecodes::_getfield , ubcp|____|clvm|____, vtos, vtos, getfield , f1_byte );def(Bytecodes::_putfield , ubcp|____|clvm|____, vtos, vtos, putfield , f2_byte );def(Bytecodes::_invokevirtual , ubcp|disp|clvm|____, vtos, vtos, invokevirtual , f2_byte );def(Bytecodes::_invokespecial , ubcp|disp|clvm|____, vtos, vtos, invokespecial , f1_byte );def(Bytecodes::_invokestatic , ubcp|disp|clvm|____, vtos, vtos, invokestatic , f1_byte );def(Bytecodes::_invokeinterface , ubcp|disp|clvm|____, vtos, vtos, invokeinterface , f1_byte );def(Bytecodes::_invokedynamic , ubcp|disp|clvm|____, vtos, vtos, invokedynamic , f1_byte );def(Bytecodes::_new , ubcp|____|clvm|____, vtos, atos, _new , _ );def(Bytecodes::_newarray , ubcp|____|clvm|____, itos, atos, newarray , _ );def(Bytecodes::_anewarray , ubcp|____|clvm|____, itos, atos, anewarray , _ );def(Bytecodes::_arraylength , ____|____|____|____, atos, itos, arraylength , _ );def(Bytecodes::_athrow , ____|disp|____|____, atos, vtos, athrow , _ );def(Bytecodes::_checkcast , ubcp|____|clvm|____, atos, atos, checkcast , _ );def(Bytecodes::_instanceof , ubcp|____|clvm|____, atos, itos, instanceof , _ );def(Bytecodes::_monitorenter , ____|disp|clvm|____, atos, vtos, monitorenter , _ );def(Bytecodes::_monitorexit , ____|____|clvm|____, atos, vtos, monitorexit , _ );def(Bytecodes::_wide , ubcp|disp|____|____, vtos, vtos, wide , _ );def(Bytecodes::_multianewarray , ubcp|____|clvm|____, vtos, atos, multianewarray , _ );def(Bytecodes::_ifnull , ubcp|____|clvm|____, atos, vtos, if_nullcmp , equal );def(Bytecodes::_ifnonnull , ubcp|____|clvm|____, atos, vtos, if_nullcmp , not_equal );def(Bytecodes::_goto_w , ubcp|____|clvm|____, vtos, vtos, goto_w , _ );def(Bytecodes::_jsr_w , ubcp|____|____|____, vtos, vtos, jsr_w , _ );// wide Java spec bytecodesdef(Bytecodes::_iload , ubcp|____|____|iswd, vtos, itos, wide_iload , _ );def(Bytecodes::_lload , ubcp|____|____|iswd, vtos, ltos, wide_lload , _ );def(Bytecodes::_fload , ubcp|____|____|iswd, vtos, ftos, wide_fload , _ );def(Bytecodes::_dload , ubcp|____|____|iswd, vtos, dtos, wide_dload , _ );def(Bytecodes::_aload , ubcp|____|____|iswd, vtos, atos, wide_aload , _ );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 , _ );// JVM bytecodesdef(Bytecodes::_fast_agetfield , ubcp|____|____|____, atos, atos, fast_accessfield , atos );def(Bytecodes::_fast_bgetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos );def(Bytecodes::_fast_cgetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos );def(Bytecodes::_fast_dgetfield , ubcp|____|____|____, atos, dtos, fast_accessfield , dtos );def(Bytecodes::_fast_fgetfield , ubcp|____|____|____, atos, ftos, fast_accessfield , ftos );def(Bytecodes::_fast_igetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos );def(Bytecodes::_fast_lgetfield , ubcp|____|____|____, atos, ltos, fast_accessfield , ltos );def(Bytecodes::_fast_sgetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos );def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos );def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );def(Bytecodes::_fast_zputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos );def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos );def(Bytecodes::_fast_iputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );def(Bytecodes::_fast_lputfield , ubcp|____|____|____, ltos, vtos, fast_storefield , ltos );def(Bytecodes::_fast_sputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );def(Bytecodes::_fast_aload_0 , ____|____|____|____, vtos, atos, aload , 0 );def(Bytecodes::_fast_iaccess_0 , ubcp|____|____|____, vtos, itos, fast_xaccess , itos );def(Bytecodes::_fast_aaccess_0 , ubcp|____|____|____, vtos, atos, fast_xaccess , atos );def(Bytecodes::_fast_faccess_0 , ubcp|____|____|____, vtos, ftos, fast_xaccess , ftos );def(Bytecodes::_fast_iload , ubcp|____|____|____, vtos, itos, fast_iload , _ );def(Bytecodes::_fast_iload2 , ubcp|____|____|____, vtos, itos, fast_iload2 , _ );def(Bytecodes::_fast_icaload , ubcp|____|____|____, vtos, itos, fast_icaload , _ );def(Bytecodes::_fast_invokevfinal , ubcp|disp|clvm|____, vtos, vtos, fast_invokevfinal , f2_byte );def(Bytecodes::_fast_linearswitch , ubcp|disp|____|____, itos, vtos, fast_linearswitch , _ );def(Bytecodes::_fast_binaryswitch , ubcp|disp|____|____, itos, vtos, fast_binaryswitch , _ );def(Bytecodes::_fast_aldc , ubcp|____|clvm|____, vtos, atos, fast_aldc , false );def(Bytecodes::_fast_aldc_w , ubcp|____|clvm|____, vtos, atos, fast_aldc , true );def(Bytecodes::_return_register_finalizer , ____|disp|clvm|____, vtos, vtos, _return , vtos );def(Bytecodes::_invokehandle , ubcp|disp|clvm|____, vtos, vtos, invokehandle , f1_byte );def(Bytecodes::_nofast_getfield , ubcp|____|clvm|____, vtos, vtos, nofast_getfield , f1_byte );def(Bytecodes::_nofast_putfield , ubcp|____|clvm|____, vtos, vtos, nofast_putfield , f2_byte );def(Bytecodes::_nofast_aload_0 , ____|____|clvm|____, vtos, atos, nofast_aload_0 , _ );def(Bytecodes::_nofast_iload , ubcp|____|clvm|____, vtos, itos, nofast_iload , _ );def(Bytecodes::_shouldnotreachhere , ____|____|____|____, vtos, vtos, shouldnotreachhere , _ );
}void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) {CodeletMark cm(_masm, Bytecodes::name(code), code);// initialize entry pointsassert(_unimplemented_bytecode != NULL, "should have been generated before");assert(_illegal_bytecode_sequence != NULL, "should have been generated before");address bep = _illegal_bytecode_sequence;address zep = _illegal_bytecode_sequence;address cep = _illegal_bytecode_sequence;address sep = _illegal_bytecode_sequence;address aep = _illegal_bytecode_sequence;address iep = _illegal_bytecode_sequence;address lep = _illegal_bytecode_sequence;address fep = _illegal_bytecode_sequence;address dep = _illegal_bytecode_sequence;address vep = _unimplemented_bytecode;address wep = _unimplemented_bytecode;// code for short & wide version of bytecodeif (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);}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);}// set entry pointsEntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep);Interpreter::_normal_table.set_entry(code, entry);Interpreter::_wentry_point[code] = wep;
}void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep) {assert(t->is_valid(), "template must exist");switch (t->tos_in()) {case btos:case ztos:case ctos:case stos:ShouldNotReachHere(); // btos/ctos/stos should use itos.break;case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break;case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break;case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break;case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break;case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break;case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break;default : ShouldNotReachHere(); break;}
}void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {if (PrintBytecodeHistogram) histogram_bytecode(t);
#ifndef PRODUCT// debugging codeif (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode();if (PrintBytecodePairHistogram) histogram_bytecode_pair(t);if (TraceBytecodes) trace_bytecode(t);if (StopInterpreterAt > 0) stop_interpreter_at();__ verify_FPU(1, t->tos_in());
#endif // !PRODUCTint step = 0;if (!t->does_dispatch()) {step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode());if (tos_out == ilgl) tos_out = t->tos_out();// compute bytecode sizeassert(step > 0, "just checkin'");// setup stuff for dispatching next bytecodeif (ProfileInterpreter && VerifyDataPointer&& MethodData::bytecode_has_profile(t->bytecode())) {__ verify_method_data_pointer();}__ dispatch_prolog(tos_out, step);}// generate templatet->generate(_masm);// advanceif (t->does_dispatch()) {
#ifdef ASSERT// make sure execution doesn't go beyond this point if code is broken__ should_not_reach_here();
#endif // ASSERT} else {// dispatch to next bytecode__ dispatch_epilog(tos_out, step);}// std::cout << "@@@@yym%%%%" << "::generate_and_dispatch" << "----end" << std::endl;
}void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) {dispatch_next(state, step);
}//
// Generic interpreted method entry to (asm) interpreter
//
address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {// determine code generation flagsbool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;// ebx: Method*// rbcp: sender spaddress entry_point = __ pc();const Address constMethod(rbx, Method::const_offset());const Address access_flags(rbx, Method::access_flags_offset());const Address size_of_parameters(rdx,ConstMethod::size_of_parameters_offset());const Address size_of_locals(rdx, ConstMethod::size_of_locals_offset());// get parameter size (always needed)__ movptr(rdx, constMethod);__ load_unsigned_short(rcx, size_of_parameters);// rbx: Method*// rcx: size of parameters// rbcp: sender_sp (could differ from sp+wordSize if we were called via c2i )__ load_unsigned_short(rdx, size_of_locals); // get size of locals in words__ subl(rdx, rcx); // rdx = no. of additional locals// YYY
// __ incrementl(rdx);
// __ andl(rdx, -2);// see if we've got enough room on the stack for locals plus overhead.generate_stack_overflow_check();//yym-gaizao// #ifdef DEBUG_PRINT_METHOD_NAME// ---yym--- 打印代码移动到堆栈检查之后{// 保存寄存器状态__ push(rax);__ push(rcx);__ push(rdx);__ push(rdi);__ push(rsi);__ push(r8);__ push(r9);__ push(r10);__ push(r11);NOT_LP64(__ get_thread(r15_thread));__ push(r15);// 准备调用参数__ movptr(rdi, rbx); // Method* 作为第一个参数__ lea(rsi, Address(rsp, 14*wordSize)); // 原始rsp地址__ mov(r8, rcx); // 参数大小__ mov(r9, rdx); // 本地变量大小// 调用调试信息输出函数__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, ::TemplateInterpreterGenerator::print_debug_info)));// 恢复寄存器__ pop(r15);NOT_LP64(__ restore_thread(r15_thread));__ pop(r11);__ pop(r10);__ pop(r9);__ pop(r8);__ pop(rsi);__ pop(rdi);__ pop(rdx);__ pop(rcx);__ pop(rax);}// #endif// get return address__ pop(rax);// compute beginning of parameters__ lea(rlocals, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize));// rdx - # of additional locals// allocate space for locals// explicitly initialize locals{Label exit, loop;__ testl(rdx, rdx);__ jcc(Assembler::lessEqual, exit); // do nothing if rdx <= 0__ bind(loop);__ push((int) NULL_WORD); // initialize local variables__ decrementl(rdx); // until everything initialized__ jcc(Assembler::greater, loop);__ bind(exit);}// initialize fixed part of activation framegenerate_fixed_frame(false);// make sure method is not native & not abstract
#ifdef ASSERT__ movl(rax, access_flags);{Label L;__ testl(rax, JVM_ACC_NATIVE);__ jcc(Assembler::zero, L);__ stop("tried to execute native method as non-native");__ bind(L);}{Label L;__ testl(rax, JVM_ACC_ABSTRACT);__ jcc(Assembler::zero, L);__ stop("tried to execute abstract method in interpreter");__ bind(L);}
#endif// Since at this point in the method invocation the exception// handler would try to exit the monitor of synchronized methods// which hasn't been entered yet, we set the thread local variable// _do_not_unlock_if_synchronized to true. The remove_activation// will check this flag.const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);NOT_LP64(__ get_thread(thread));const Address do_not_unlock_if_synchronized(thread,in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));__ movbool(do_not_unlock_if_synchronized, true);__ profile_parameters_type(rax, rcx, rdx);// increment invocation count & check for overflowLabel invocation_counter_overflow;if (inc_counter) {generate_counter_incr(&invocation_counter_overflow);}Label continue_after_compile;__ bind(continue_after_compile);// check for synchronized interpreted methodsbang_stack_shadow_pages(false);// reset the _do_not_unlock_if_synchronized flagNOT_LP64(__ get_thread(thread));__ movbool(do_not_unlock_if_synchronized, false);// check for synchronized methods// Must happen AFTER invocation_counter check and stack overflow check,// so method is not locked if overflows.if (synchronized) {// Allocate monitor and lock methodlock_method();} else {// no synchronization necessary
#ifdef ASSERT{Label L;__ movl(rax, access_flags);__ testl(rax, JVM_ACC_SYNCHRONIZED);__ jcc(Assembler::zero, L);__ stop("method needs synchronization");__ bind(L);}
#endif}// start execution
#ifdef ASSERT{Label L;const Address monitor_block_top (rbp,frame::interpreter_frame_monitor_block_top_offset * wordSize);__ movptr(rax, monitor_block_top);__ cmpptr(rax, rsp);__ jcc(Assembler::equal, L);__ stop("broken stack frame setup in interpreter");__ bind(L);}
#endif// jvmti support__ notify_method_entry();__ dispatch_next(vtos);// invocation counter overflowif (inc_counter) {// Handle overflow of counter and compile method__ bind(invocation_counter_overflow);generate_counter_overflow(continue_after_compile);}return entry_point;
}void InterpreterMacroAssembler::dispatch_next(TosState state, int step, bool generate_poll) {// load next bytecode (load before advancing _bcp_register to prevent AGI)load_unsigned_byte(rbx, Address(_bcp_register, step));// advance _bcp_registerincrement(_bcp_register, step);dispatch_base(state, Interpreter::dispatch_table(state), true, generate_poll);
}void InterpreterMacroAssembler::dispatch_base(TosState state,address* table,bool verifyoop,bool generate_poll) {verify_FPU(1, state);if (VerifyActivationFrameSize) {Label L;mov(rcx, rbp);subptr(rcx, rsp);int32_t min_frame_size =(frame::link_offset - frame::interpreter_frame_initial_sp_offset) *wordSize;cmpptr(rcx, (int32_t)min_frame_size);jcc(Assembler::greaterEqual, L);stop("broken stack frame");bind(L);}if (verifyoop) {interp_verify_oop(rax, state);}address* const safepoint_table = Interpreter::safept_table(state);
#ifdef _LP64Label no_safepoint, dispatch;if (table != safepoint_table && generate_poll) {NOT_PRODUCT(block_comment("Thread-local Safepoint poll"));testb(Address(r15_thread, JavaThread::polling_word_offset()), SafepointMechanism::poll_bit());jccb(Assembler::zero, no_safepoint);lea(rscratch1, ExternalAddress((address)safepoint_table));jmpb(dispatch);}bind(no_safepoint);lea(rscratch1, ExternalAddress((address)table));bind(dispatch);jmp(Address(rscratch1, rbx, Address::times_8));#elseAddress index(noreg, rbx, Address::times_ptr);if (table != safepoint_table && generate_poll) {NOT_PRODUCT(block_comment("Thread-local Safepoint poll"));Label no_safepoint;const Register thread = rcx;get_thread(thread);testb(Address(thread, JavaThread::polling_word_offset()), SafepointMechanism::poll_bit());jccb(Assembler::zero, no_safepoint);ArrayAddress dispatch_addr(ExternalAddress((address)safepoint_table), index);jump(dispatch_addr);bind(no_safepoint);}{ArrayAddress dispatch_addr(ExternalAddress((address)table), index);jump(dispatch_addr);}
#endif // _LP64
}static address* dispatch_table(TosState state) { return _active_table.table_for(state); }void TemplateInterpreter::initialize_code() {AbstractInterpreter::initialize();TemplateTable::initialize();// generate interpreter{ ResourceMark rm;TraceTime timer("Interpreter generation", TRACETIME_LOG(Info, startuptime));TemplateInterpreterGenerator g(_code);// Free the unused memory not occupied by the interpreter and the stubs_code->deallocate_unused_tail();}if (PrintInterpreter) {ResourceMark rm;print();}// initialize dispatch table_active_table = _normal_table;
}