当前位置: 首页 > ds >正文

OpenJDK 17 解释器分发表与安全点表机制解析

概述

在 OpenJDK 17 的解释器实现中,有两个关键的数据结构负责管理字节码的执行入口:_normal_table(正常分发表)和 safepoint_table(安全点表)。这些表结构确保了字节码能够高效地在正常状态和安全点状态下执行。本文将深入分析这些数据结构的实现原理和工作机制。

分发表(DispatchTable)的实现

基本结构

DispatchTable 类是解释器核心组件之一,它管理着所有字节码的执行入口点:

cpp

void DispatchTable::set_entry(int i, EntryPoint& entry) {assert(0 <= i && i < length, "index out of bounds");assert(number_of_states == 10, "check the code below");_table[btos][i] = entry.entry(btos);_table[ztos][i] = entry.entry(ztos);_table[ctos][i] = entry.entry(ctos);// ... 其他 TosState 类型
}

每个字节码索引 i 对应一个 EntryPoint 对象,该对象包含了该字节码在不同栈顶状态(TosState)下的执行入口地址。OpenJDK 支持 10 种不同的栈顶状态,包括 btos(boolean)、ztos(boolean,与 btos 类似)、ctos(char)等。

EntryPoint 结构

EntryPoint 是一个封装类,它存储了一个字节码在所有 TosState 下的执行入口:

cpp

EntryPoint DispatchTable::entry(int i) const {assert(0 <= i && i < length, "index out of bounds");return EntryPoint(_table[btos][i],_table[ztos][i],_table[ctos][i],// ... 其他状态);
}

正常表(_normal_table)的初始化

设置所有字节码的入口点

解释器初始化过程中,会为所有字节码设置相应的入口点:

cpp

void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() {for (int i = 0; i < DispatchTable::length; i++) {Bytecodes::Code code = (Bytecodes::Code)i;if (Bytecodes::is_defined(code)) {set_entry_points(code);} else {set_unimplemented(i);}}
}

具体字节码入口设置

对于已定义的字节码,解释器会根据字节码特性设置相应的入口点:

cpp

void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) {CodeletMark cm(_masm, Bytecodes::name(code), code);// 初始化各种 TosState 的入口点address bep = _illegal_bytecode_sequence;address zep = _illegal_bytecode_sequence;// ... 其他状态初始化if (Bytecodes::is_defined(code)) {Template* t = TemplateTable::template_for(code);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);set_wide_entry_point(t, wep);}EntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep);Interpreter::_normal_table.set_entry(code, entry);Interpreter::_wentry_point[code] = wep;
}

未实现字节码处理

对于未实现的字节码,统一设置为未实现入口点:

cpp

void TemplateInterpreterGenerator::set_unimplemented(int i) {address e = _unimplemented_bytecode;EntryPoint entry(e, e, e, e, e, e, e, e, e, e);Interpreter::_normal_table.set_entry(i, entry);Interpreter::_wentry_point[i] = _unimplemented_bytecode;
}

安全点表(safepoint_table)机制

安全点入口生成

安全点表负责管理在安全点状态下字节码的执行入口。这些入口点会调用运行时例程处理安全点操作:

cpp

{ CodeletMark cm(_masm, "safepoint entry points");Interpreter::_safept_entry =EntryPoint(generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),// ... 其他状态);}

安全点表初始化

安全点表使用与正常表相同的结构,但所有入口都指向安全点处理例程:

cpp

void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() {for (int i = 0; i < DispatchTable::length; i++) {Bytecodes::Code code = (Bytecodes::Code)i;if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry);}
}

安全点表访问

安全点表通过状态获取相应的分发表:

cpp

static address* safept_table(TosState state) { return _safept_table.table_for(state); }// 使用示例
address* const safepoint_table = Interpreter::safept_table(state);

模板表(TemplateTable)的作用

模板表负责为每个字节码生成实际的机器代码模板:

cpp

void TemplateTable::def(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(int arg), int arg) {bool is_wide = (flags & iswd) != 0;// 宽指令只有 vtos 入口点assert(in == vtos || !is_wide, "wide instructions have vtos entry point only");Template* t = is_wide ? template_for_wide(code) : template_for(code);t->initialize(flags, in, out, gen, arg);assert(t->bytecode() == code, "just checkin'");
}

总结

OpenJDK 17 的解释器通过精细的分发表机制实现了高效的字节码执行:

  1. 双表结构:正常表和安全点表分别处理普通执行和安全点状态下的字节码分发

  2. 状态感知:每个字节码有多个入口点,适应不同的栈顶状态(TosState)

  3. 模板化代码生成:通过 TemplateTable 为每个字节码生成优化的机器代码

  4. 统一未实现处理:对未实现或非法字节码提供统一的错误处理机制

这种设计既保证了解释执行的效率,又提供了安全点机制所需的灵活性,是 JVM 解释器实现的核心技术之一。理解这些数据结构和工作原理对于深入理解 JVM 内部机制具有重要意义。

##源码

void DispatchTable::set_entry(int i, EntryPoint& entry) {assert(0 <= i && i < length, "index out of bounds");assert(number_of_states == 10, "check the code below");_table[btos][i] = entry.entry(btos);_table[ztos][i] = entry.entry(ztos);_table[ctos][i] = entry.entry(ctos);_table[stos][i] = entry.entry(stos);_table[atos][i] = entry.entry(atos);_table[itos][i] = entry.entry(itos);_table[ltos][i] = entry.entry(ltos);_table[ftos][i] = entry.entry(ftos);_table[dtos][i] = entry.entry(dtos);_table[vtos][i] = entry.entry(vtos);
}//------------------------------------------------------------------------------------------------------------------------
// Implementation of DispatchTableEntryPoint DispatchTable::entry(int i) const {assert(0 <= i && i < length, "index out of bounds");returnEntryPoint(_table[btos][i],_table[ztos][i],_table[ctos][i],_table[stos][i],_table[atos][i],_table[itos][i],_table[ltos][i],_table[ftos][i],_table[dtos][i],_table[vtos][i]);
}{ CodeletMark cm(_masm, "safepoint entry points");Interpreter::_safept_entry =EntryPoint(generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)));}void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() {for (int i = 0; i < DispatchTable::length; i++) {Bytecodes::Code code = (Bytecodes::Code)i;if (Bytecodes::is_defined(code)) {set_entry_points(code);} else {set_unimplemented(i);}}
}void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() {for (int i = 0; i < DispatchTable::length; i++) {Bytecodes::Code code = (Bytecodes::Code)i;if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry);}
}static address*   safept_table(TosState state)                { return _safept_table.table_for(state); }address* const safepoint_table = Interpreter::safept_table(state);  void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() {for (int i = 0; i < DispatchTable::length; i++) {Bytecodes::Code code = (Bytecodes::Code)i;if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry);}
}void TemplateInterpreterGenerator::set_unimplemented(int i) {address e = _unimplemented_bytecode;EntryPoint entry(e, e, e, e, e, e, e, e, e, e);Interpreter::_normal_table.set_entry(i, entry);Interpreter::_wentry_point[i] = _unimplemented_bytecode;
}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;
}/**
static Template* template_for     (Bytecodes::Code code)  { Bytecodes::check     (code); return &_template_table     [code]; }
_template_table初始化,拿到code索引指针,初始化t->initialize
*/
void TemplateTable::def(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(int arg), int arg) {// should factor out these constantsconst int iswd = 1 << Template::wide_bit;// determine which table to usebool 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 entryt->initialize(flags, in, out, gen, arg);assert(t->bytecode() == code, "just checkin'");
}void TemplateTable::def(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(Operation op), Operation op) {def(code, flags, in, out, (Template::generator)gen, (int)op);
}

http://www.xdnf.cn/news/19526.html

相关文章:

  • 零基础入门AutoSar中的ARXML文件
  • 【Flask】测试平台开发,产品管理功能UI重构-第九篇
  • Kubernetes 服务发现与健康检查详解
  • 搭建卷积神经网络
  • 软考 系统架构设计师系列知识点之杂项集萃(139)
  • C++11语言(三)
  • Nginx实现P2P视频通话
  • codecombat(Ubuntu环境详细docker部署教程)
  • 项目-云备份
  • 面试 八股文 经典题目 - HTTPS部分(一)
  • Flink NettyBufferPool
  • 大模型时代:用Redis构建百亿级向量数据库方
  • EtherCAT主站IGH-- 41 -- IGH之sdo_request.h/c文件解析
  • Library cache lock常见案例分析(一)
  • Encoder编码器
  • 图像描述编辑器 (Image Caption Editor)
  • 极客时间AI 全栈开发实战营毕业总结(2025年8月31日)
  • 【Linux基础】深入理解计算机存储:GPT分区表详解
  • 前端组件拆分与管理实战:如何避免 props 地狱,写出高可维护的项目
  • 《Unity Shader入门精要》学习笔记四(高级纹理)
  • ing Data JPA 派生方法 数据操作速查表
  • 【WEB】[BUUCTF] <GXYCTF2019禁止套娃>《php函数的运用》
  • ADC platfrom day65
  • MVC架构模式
  • Blender建模:对于模型布线的一些思考
  • 介绍GSPO:一种革命性的语言模型强化学习算法
  • 现代C++性能陷阱:std::function的成本、异常处理的真实开销
  • Luma 视频生成 API 对接说明
  • AI 智能体汇总,自动执行任务的“真 Agent”
  • 查看所有装在c盘软件的方法