Files
OxideJS-New/crates/oxide_bytecode/src/opcode.rs
T

999 lines
55 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 字节码操作码表与指令编解码。
//!
//! [`OpCode`] 由 `define_opcodes!` 宏从单张表生成(每行含语义字段
//! def/uses/pure/jump/term/ic);[`Instr`] 是 4 字节指令(opcode + rd + a + b,
//! imm16/offset16 复用 a、b 两字节)。本模块提供编译器发射(`encode*`)与 VM
//! 解码(`opcode` / `rd` / `a` / `b` 等)全套函数。
use std::fmt;
/// 操作数槽位:指令 rd/a/b 三槽之一。
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Slot {
/// 目标寄存器槽。
Rd,
/// 第一操作数槽。
A,
/// 第二操作数槽。
B,
}
/// 槽位规范:声明指令如何读写寄存器。解析器在 `oxide_ir::contract`。
///
/// # 语义约定
/// - `Slot(Rd|A|B)`:读/写对应操作数槽;Const/Imm/Label 非寄存器则跳过;
/// None→0、This→254、NewTarget→255 由操作数层 reg_of 映射(不进表)。
/// - `Reg0`:常量寄存器 0(CALL 隐式写、HALT 隐式读)。
/// - `Range(Slot)`:从指定槽起连续 nargs 个寄存器,nargs=ext[0](调用实参区)。
/// - `SpreadArgs`:ext[1..] 每个字 `& 0x7FFF_FFFF` 是实参寄存器(spread 源同低 31 位)。
/// - `TemplateExprs`:TEMPLATE_STR 的 ext[1..],`seg>>31==1` 时低 8 位是表达式寄存器。
/// - `BrandReg`:ext[0] 是 brand 对象寄存器,0 表示跳过检查(不产生 use)。
/// - `ExtReg`:ext[0] 是寄存器,高位标记 `0x8000_0000 | vreg`,低 31 位是 vreg。
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SlotSpec {
/// 读写对应操作数槽。
Slot(Slot),
/// 常量寄存器 0。
Reg0,
/// 从指定槽起连续 nargs 个寄存器(nargs=ext[0])。
Range(Slot),
/// spread 调用系 ext[1..] 的有序实参字。
SpreadArgs,
/// TEMPLATE_STR 的 ext[1..] 表达式寄存器。
TemplateExprs,
/// ext[0] 的 brand 对象寄存器(0 跳过检查)。
BrandReg,
/// ext[0] 的寄存器(高位标记,与 SpreadArgs 同款编码)。
ExtReg,
}
/// 单张语义表行:一个 opcode 的 def/uses/pure/跳转/终结/IC 扩展字声明。
///
/// 字段语义与各消费方判定集合一致:`is_jump` = lower.rs 跳转族(label
/// 回填),`is_terminator` = CFG 块尾终结,`ic_ext` = VM 的 IC 扩展字。`pure`
/// 是静态可删判定,LOAD_VAR 的上下文例外留在 `oxide_ir::contract::is_pure`。
pub struct OpSemantics {
/// 写入的寄存器(恒为单个,无 Range)。
pub def: Option<SlotSpec>,
/// 读取的寄存器(按序,序即 use_regs 输出序)。
pub uses: &'static [SlotSpec],
/// 静态可删判定(LOAD_VAR 例外在 oxide_ir 侧)。
pub pure: bool,
/// 带 Label 槽、需偏移回填(= lower.rs is_jump_op)。
pub is_jump: bool,
/// CFG 块尾终结(= cfg is_terminator)。
pub is_terminator: bool,
/// IC 扩展字(= has_ic_ext_words):每条 IC 指令带 IC_EXT_WORDS 个扩展字。
pub ic_ext: bool,
}
/// IC 每站点的缓存槽数:多态化支持同一访问点最多缓存该数量的 shape。
pub const IC_SLOTS: usize = 4;
/// 每条 IC 指令的扩展字总数(每槽两个字:shape_id|proto_depth 打包字 + slot 字)。
pub const IC_EXT_WORDS: usize = IC_SLOTS * 2;
/// 从单张表生成 [`OpCode`] 枚举、`TryFrom<u8>`、`Display` 与语义访问器。
///
/// 每行同时提供枚举判别值、`TryFrom` 分支、`Display` 名称与语义字段
/// (def/uses/pure/jump/term/ic)七份信息,保证多表永不漂移;新增操作码只需
/// 加一行。`semantics()` 的 match 无 `_` 臂——漏填语义即编译错误。
///
/// # 注意事项
/// - 分组注释(`// ── 算术 ──`)在宏展开前被词法器剥离,可自由插入行间。
macro_rules! define_opcodes {
( $(
$name:ident = $val:literal => $disp:literal,
def = $def:expr, uses = [$($u:expr),*],
pure = $pure:literal, jump = $jump:literal, term = $term:literal, ic = $ic:literal
),+ $(,)? ) => {
/// 寄存器字节码虚拟机的操作码。
///
/// 按 16 个一组组织便于阅读。已实现的操作码在编译器中有发射支持;
/// 占位符操作码为后续阶段预留(IC、profiling、并行化)。
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum OpCode {
$( $name = $val, )+
}
impl TryFrom<u8> for OpCode {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
$( $val => Ok(OpCode::$name), )+
_ => Err(()),
}
}
}
impl fmt::Display for OpCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self {
$( OpCode::$name => $disp, )+
};
write!(f, "{name}")
}
}
impl OpCode {
/// 单张语义表访问器。match 无 `_` 臂:新 opcode 漏填语义即编译错误。
///
/// # 注意事项
/// - 返回 `&'static`:match 臂内 `&OpSemantics { .. }` 是常量表达式,
/// 由常量提升保证零运行时开销。
pub fn semantics(&self) -> &'static OpSemantics {
match self {
$( OpCode::$name => &OpSemantics {
def: $def,
uses: &[$($u),*],
pure: $pure,
is_jump: $jump,
is_terminator: $term,
ic_ext: $ic,
}, )+
}
}
/// 便捷访问器:跳转族(label 偏移回填)。
pub fn is_jump(&self) -> bool {
self.semantics().is_jump
}
/// 便捷访问器:CFG 块尾终结。
pub fn is_terminator(&self) -> bool {
self.semantics().is_terminator
}
/// 便捷访问器:IC 扩展字。
pub fn has_ic_ext_words(&self) -> bool {
self.semantics().ic_ext
}
}
};
}
define_opcodes! {
// ── Arithmetic (0x00-0x0F) ──
ADD = 0x00 => "ADD",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
SUB = 0x01 => "SUB",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
MUL = 0x02 => "MUL",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
DIV = 0x03 => "DIV",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
MOD = 0x04 => "MOD",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
NEG = 0x05 => "NEG",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_ADD = 0x06 => "COMPOUND_ADD",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_SUB = 0x07 => "COMPOUND_SUB",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_MUL = 0x08 => "COMPOUND_MUL",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_DIV = 0x09 => "COMPOUND_DIV",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_MOD = 0x0A => "COMPOUND_MOD",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_EXP = 0x0B => "COMPOUND_EXP",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
// 二元幂运算 `a ** b`(三寄存器,与 SUB/MUL 同族;0x00-0x0F 已满,值用空闲槽 0x94)。
EXP = 0x94 => "EXP",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
MOV = 0x0C => "MOV", // rd=dst, a=src(寄存器复制,区间拆分搬值)
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = true, jump = false, term = false, ic = false,
SPILL = 0x0D => "SPILL", // rd=src, ext=[slot u16](寄存器值写 VM spill 栈)
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
UNSPILL = 0x0E => "UNSPILL", // rd=dst, ext=[slot u16](从 VM spill 栈恢复寄存器)
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
SPREAD_OBJECT = 0x0F => "SPREAD_OBJECT", // rd=目标对象, a=源(对象字面量 ... 展开,原地写目标)
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
// ── 比较 (0x10-0x1F) ──
EQ = 0x10 => "EQ",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
NEQ = 0x11 => "NEQ",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
LT = 0x12 => "LT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
GT = 0x13 => "GT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
LTE = 0x14 => "LTE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
GTE = 0x15 => "GTE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
IN = 0x16 => "IN",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
NOT = 0x17 => "NOT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = true, jump = false, term = false, ic = false,
AND = 0x18 => "AND",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = true, jump = false, term = false, ic = false,
OR = 0x19 => "OR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = true, jump = false, term = false, ic = false,
STRICT_EQ = 0x1A => "STRICT_EQ",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = true, jump = false, term = false, ic = false,
STRICT_NEQ = 0x1C => "STRICT_NEQ",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = true, jump = false, term = false, ic = false,
UNARY_PLUS = 0x1D => "UNARY_PLUS",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
// ── 控制流 (0x1E-0x2F) ──
BREAK = 0x1E => "BREAK",
def = None, uses = [],
pure = false, jump = true, term = true, ic = false,
CONTINUE = 0x1F => "CONTINUE",
def = None, uses = [],
pure = false, jump = true, term = true, ic = false,
JMP = 0x20 => "JMP",
def = None, uses = [],
pure = false, jump = true, term = true, ic = false,
JMP_IF_FALSE = 0x21 => "JMP_IF_FALSE",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = true, term = true, ic = false,
JMP_IF_TRUE = 0x22 => "JMP_IF_TRUE",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = true, term = true, ic = false,
FOR_OF_INIT = 0x23 => "FOR_OF_INIT",
def = None, uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
FOR_OF_NEXT = 0x24 => "FOR_OF_NEXT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
// ── 更新 (0x25-0x28) ──
INC_PRE = 0x25 => "INC_PRE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
INC_POST = 0x26 => "INC_POST",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
DEC_PRE = 0x27 => "DEC_PRE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
DEC_POST = 0x28 => "DEC_POST",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
FOR_IN_INIT = 0x29 => "FOR_IN_INIT",
def = None, uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
FOR_IN_NEXT = 0x2A => "FOR_IN_NEXT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
FOR_IN_DONE = 0x2B => "FOR_IN_DONE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
// using/await using 声明登记:rd = 资源值寄存器,a = 释放提示(0 = 同步、1 = 异步)。
// 无寄存器 def(值压入 VM 释放栈,释放时机由作用域出口点决定);
// pure = false 防 DCE 删除压栈副作用。
DISPOSE_REGISTER = 0x2C => "DISPOSE_REGISTER",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
FOR_IN_CLEANUP = 0x2D => "FOR_IN_CLEANUP",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
// ── 异常 (0x2E-0x2F, 0x33-0x35;TRY_FINALLY_ENTER 用 0x1B 空槽) ──
THROW = 0x2E => "THROW",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = true, ic = false,
TRY_BEGIN = 0x2F => "TRY_BEGIN",
def = None, uses = [],
pure = false, jump = true, term = false, ic = false,
TRY_END = 0x33 => "TRY_END",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
TRY_FINALLY_BEGIN = 0x34 => "TRY_FINALLY_BEGIN",
def = None, uses = [],
pure = false, jump = true, term = false, ic = false,
TRY_FINALLY_ENTER = 0x1B => "TRY_FINALLY_ENTER",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
TRY_FINALLY_END = 0x35 => "TRY_FINALLY_END",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
FOR_OF_DONE = 0x36 => "FOR_OF_DONE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
FOR_OF_CLOSE = 0x37 => "FOR_OF_CLOSE",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
// ── 模板字符串 (0x38) ──
TEMPLATE_STR = 0x38 => "TEMPLATE_STR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::TemplateExprs],
pure = false, jump = false, term = false, ic = false,
// ── 标签模板对象 (0x97) ──
// GetTemplateObject:按 site 缓存模板对象(同一编译树同 site 恒返回同一对象),
// 首次构建时冻结 cooked/raw 数组并设置规范描述符。ext 布局见
// `Inst::get_template_object`;无寄存器 use(quasis 全为常量池下标)。
GET_TEMPLATE_OBJECT = 0x97 => "GET_TEMPLATE_OBJECT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
// ── 小语言特性 (0x39-0x3B) ──
DELETE_PROP_STATIC = 0x39 => "DELETE_PROP_STATIC",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
DELETE_PROP_DYNAMIC = 0x3A => "DELETE_PROP_DYNAMIC",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
INSTANCEOF = 0x3B => "INSTANCEOF",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
MAKE_CELL = 0x3C => "MAKE_CELL",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
CELL_GET = 0x3D => "CELL_GET",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = true, jump = false, term = false, ic = false,
REST_OBJECT = 0x3E => "REST_OBJECT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
CELL_SET = 0x3F => "CELL_SET",
def = None, uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
// ── 变量 (0x30-0x32) ──
LOAD_VAR = 0x30 => "LOAD_VAR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = true, jump = false, term = false, ic = false,
STORE_VAR = 0x31 => "STORE_VAR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
LOAD_CONST = 0x32 => "LOAD_CONST",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
// 未声明/已删标识符读:rd=目标,a/b=常量池 key 下标(imm16,与 LOAD_CONST 同构),
// 运行期查 global object 属性存在性,缺失抛 ReferenceError(未声明名与已知 builtin
// 名非局部遮蔽读均命中本指令:delete 后 A 侧缺失须经属性在位判定,镜像槽无法
// 自区分缺位与在位 undefined)。
LOAD_GLOBAL = 0x95 => "LOAD_GLOBAL",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
// typeof 未声明标识符特判:同 LOAD_GLOBAL 查 global object 属性,但缺失时
// 求值为 undefined 而非抛 ReferenceError(IsUnresolvableReference 语义)。
LOAD_GLOBAL_TYPEOF = 0x96 => "LOAD_GLOBAL_TYPEOF",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
// ── 调用 (0x40-0x4F) ──
CALL = 0x40 => "CALL", // 结果隐式写 reg 0;rd=callee, a=this, b=首参, ext[0]=nargs
def = Some(SlotSpec::Reg0), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Range(Slot::B)],
pure = false, jump = false, term = false, ic = false,
RETURN = 0x41 => "RETURN",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = true, ic = false,
CALL_NATIVE = 0x42 => "CALL_NATIVE",
def = Some(SlotSpec::Reg0), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Range(Slot::B)],
pure = false, jump = false, term = false, ic = false,
NEW_EXPRESSION = 0x43 => "NEW_EXPRESSION", // a=ctor, b..b+nargs
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Range(Slot::B)],
pure = false, jump = false, term = false, ic = false,
SUPER_CALL = 0x44 => "SUPER_CALL", // a..a+nargs,无 callee/this 槽
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Range(Slot::A)],
pure = false, jump = false, term = false, ic = false,
SUPER_GET_PROP = 0x45 => "SUPER_GET_PROP",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
SUPER_STATIC_GET_PROP = 0x46 => "SUPER_STATIC_GET_PROP",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
SET_HOME_OBJECT = 0x47 => "SET_HOME_OBJECT",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
DEFINE_ACCESSOR = 0x48 => "DEFINE_ACCESSOR",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
LOAD_UPVALUE = 0x49 => "LOAD_UPVALUE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
CREATE_CLOSURE = 0x4A => "CREATE_CLOSURE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
CREATE_REGEXP = 0x4B => "CREATE_REGEXP",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
STORE_UPVALUE = 0x4C => "STORE_UPVALUE",
def = None, uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
CALL_SPREAD = 0x4D => "CALL_SPREAD", // 结果经 reg 0;ext[1..] 有序实参字
def = Some(SlotSpec::Reg0), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::SpreadArgs],
pure = false, jump = false, term = false, ic = false,
NEW_EXPRESSION_SPREAD = 0x4E => "NEW_EXPRESSION_SPREAD",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::SpreadArgs],
pure = false, jump = false, term = false, ic = false,
SUPER_CALL_SPREAD = 0x4F => "SUPER_CALL_SPREAD",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::SpreadArgs],
pure = false, jump = false, term = false, ic = false,
// ── Object Property (0x50-0x5F) ──
IC_GET_PROP = 0x50 => "IC_GET_PROP", // a 槽既是对象 use 又写回结果,rd 忽略
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
IC_SET_PROP = 0x51 => "IC_SET_PROP",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
GET_PROP = 0x52 => "GET_PROP", // 结果写 a 槽,rd=obj 是 use
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
GET_PROP_DYNAMIC = 0x53 => "GET_PROP_DYNAMIC", // 结果写 b 槽
def = Some(SlotSpec::Slot(Slot::B)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
SET_PROP = 0x54 => "SET_PROP",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
SET_PROP_DYNAMIC = 0x55 => "SET_PROP_DYNAMIC",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// a 槽编码纯静态数据键前缀的属性数(≤255),ext 为每键的常量池下标;
// 运行时按键序链式预建 shape,后续 SET_PROP_BATCH 纯槽写。
NEW_OBJECT = 0x56 => "NEW_OBJECT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
NEW_ARRAY = 0x57 => "NEW_ARRAY",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
SET_ELEM = 0x58 => "SET_ELEM",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// 对象字面量批量构造的纯槽写:rd=对象,a=值,b=Imm(slot)。键序预建的 shape 槽,
// 不做任何键解析/形状变更,仅写数据槽。
SET_PROP_BATCH = 0x92 => "SET_PROP_BATCH",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// 多操作数拼接(连续 `+` 左结合链摊平):rd=结果,a=首操作数,ext=[n, op2..opn],
// n=操作数总数,ext 字数 = 1+(n-1) = n;op 字无高位标记(纯 vreg,≤255),
// SpreadArgs 直接解析。含 ToPrimitive 副作用,不可删。
CONCAT_N = 0x93 => "CONCAT_N",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::SpreadArgs],
pure = false, jump = false, term = false, ic = false,
// ── 成员更新 (0x59-0x62) ──
MEMBER_INC = 0x59 => "MEMBER_INC", // 结果写 a 槽(val 槽原地更新)
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
MEMBER_DEC = 0x5A => "MEMBER_DEC",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
DYN_MEMBER_INC = 0x5B => "DYN_MEMBER_INC", // 结果写 b 槽
def = Some(SlotSpec::Slot(Slot::B)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
DYN_MEMBER_DEC = 0x5C => "DYN_MEMBER_DEC",
def = Some(SlotSpec::Slot(Slot::B)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_MEMBER_ADD = 0x5D => "COMPOUND_MEMBER_ADD",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_SUB = 0x5E => "COMPOUND_MEMBER_SUB",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_MUL = 0x5F => "COMPOUND_MEMBER_MUL",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_DIV = 0x60 => "COMPOUND_MEMBER_DIV",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_MOD = 0x61 => "COMPOUND_MEMBER_MOD",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_EXP = 0x62 => "COMPOUND_MEMBER_EXP",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
// ── 对象 (0x63) ──
CREATE_ARGUMENTS = 0x63 => "CREATE_ARGUMENTS",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
// rest 参数数组:rd=目标寄存器,b=固定形参数(rest 之前的形参个数)。
CREATE_REST_ARRAY = 0x6E => "CREATE_REST_ARRAY",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
// ── using/await using 释放 (0x6A, 0x6B) ──
// 作用域入口水位:把当前释放栈深度压入水位栈(DISPOSE_REGISTER 的配对出口),
// 无寄存器 def/use;pure = false 防 DCE 删除水位副作用。
DISPOSE_MARK = 0x6A => "DISPOSE_MARK",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
// 作用域出口:弹出水位,逆序释放水位以上资源并截断释放栈(规范
// DisposeResources),无寄存器 def/use。
DISPOSE_POP = 0x6B => "DISPOSE_POP",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
// super 属性写:rd=值、a=this(receiver)、b=键。运行期 GetSuperBase 先于
// ToPropertyKey(与 SUPER_GET_PROP 同步序),基非对象抛 TypeError,写经
// ordinary_set(strict 由 current_strict 判定,失败抛 TypeError)。
SUPER_PUT_PROP = 0x6C => "SUPER_PUT_PROP",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// ── define 语义属性写入 (0x6D, 0x6F) ──
DEFINE_PROP = 0x6D => "DEFINE_PROP",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// 全局 var 绑定属性定义:rd=目标对象、a=值、b=键,数据属性可写/可枚举/不可配置
// (脚本顶层 var/function 声明同步到 globalThis 用,属性描述符与规范一致)。
DEFINE_GLOBAL_PROP = 0x6F => "DEFINE_GLOBAL_PROP",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// define 数据/访问器属性并指定描述符:ext 字存放 attrs(bit0=writable, bit1=enumerable, bit2=configurable,与 PropAttributes 位一致)。
// class 方法/constructor/prototype 需要非枚举或不可写描述符,普通 SET_PROP/DEFINE_PROP 无法表达。
DEFINE_PROP_ATTRS = 0x90 => "DEFINE_PROP_ATTRS",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
DEFINE_ACCESSOR_ATTRS = 0x91 => "DEFINE_ACCESSOR_ATTRS",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// 隐式全局写:ext 字 = 键常量池下标(u16)、a 槽 = 值寄存器;全局对象由 VM 运行期
// 从 session 取(不依赖 this——函数体内隐式全局写时 regs[254] 不一定是全局对象)。
// 数据属性可写/可枚举/可配置(未声明标识符 PutValue 与 eval 脚本声明共用);
// 全局对象不可扩展时 strict/sloppy 均抛 TypeError。
DEFINE_GLOBAL_PROP_C = 0x98 => "DEFINE_GLOBAL_PROP_C",
def = None, uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
// 顶层 var 声明的全局属性 define-if-absent(GDI 序言):rd=目标对象(顶层
// This=全局对象)、a=值、b=键。既有属性(数据或 accessor)零动作——
// CreateGlobalVarBinding 对既有数据描述符零修改(可写/不可写/配置位均不更新);
// 缺失新建可写/可枚举/不可配置数据属性(脚本 var 的 c:false 描述符)。
DEFINE_GLOBAL_PROP_IF_ABSENT = 0x99 => "DEFINE_GLOBAL_PROP_IF_ABSENT",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// eval 脚本顶层 var 声明的全局属性 define-if-absent:ext 字 = 键常量池下标
// (u16)、a 槽 = 值寄存器;全局对象由 session 解析(不依赖 this)。既有属性
// 零动作,缺失新建可写/可枚举/可配置(eval 传 deterministic=true)。
DEFINE_GLOBAL_PROP_C_IF_ABSENT = 0x9A => "DEFINE_GLOBAL_PROP_C_IF_ABSENT",
def = None, uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
// session 直分普通对象:寿命 session 级(session GC mark/sweep 回收),逃逸写
// 不触发晋升克隆。类原型等内建形对象要求与构造器 prototype 属性两侧 identity
// 一致——epoch 分配会在逃逸写晋升时克隆出第二份分裂 identity(同函数
// prototype 子对象的 session 分配同因)。
NEW_SESSION_OBJECT = 0x9B => "NEW_SESSION_OBJECT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
// 删除全局内置数据属性(delete 标识符):ext 字 = 键常量池下标(u16)、
// rd = 布尔结果槽、a 槽 = 内置镜像槽寄存器(删除成功时该槽写 undefined;
// 0 = 无槽)。全局对象由 VM 运行期从 session 取(不依赖 this 寄存器)。
DELETE_GLOBAL_PROP_C = 0x9C => "DELETE_GLOBAL_PROP_C",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
// 全局函数绑定声明检查(GDI step 9,脚本顶层函数声明):rd=目标对象(顶层
// This=全局对象)、b=键寄存器。CanDeclareGlobalFunction 三臂:缺失 →
// IsExtensible、c:true → 过、data{w:true,e:true} → 过,余抛 TypeError。
// 检查阶段发射于任何绑定创建之前(先于 GDI var 序言),失败即无部分绑定。
CAN_DECLARE_GLOBAL_FUNC = 0x9D => "CAN_DECLARE_GLOBAL_FUNC",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// 创建全局函数绑定(CreateGlobalFunctionBinding,脚本面 deletable=false):
// rd=目标对象、a=值、b=键,与 DEFINE_GLOBAL_PROP 同形。缺失或既有 c:true →
// 定义可写/可枚举/不可配置数据属性;既有 c:false 可写数据 → 仅更新值保描述符。
DEFINE_GLOBAL_FUNC_BIND = 0x9E => "DEFINE_GLOBAL_FUNC_BIND",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// 计算键访问器并指定描述符:同形 DEFINE_ACCESSOR_ATTRS,但 ext[0] 为高位标记
// 键寄存器(`0x8000_0000 | key_reg`,键值运行期从寄存器读取)、ext[1] = attrs。
// 发射方仅 class 体计算 get/set(规范 DefineMethod,enumerable=false)。
DEFINE_ACCESSOR_ATTRS_DYNAMIC = 0x9F => "DEFINE_ACCESSOR_ATTRS_DYNAMIC",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B), SlotSpec::ExtReg],
pure = false, jump = false, term = false, ic = false,
// ── 成员复合赋值:位/移位 (0x64-0x69) ──
COMPOUND_MEMBER_BIT_AND = 0x64 => "COMPOUND_MEMBER_BIT_AND",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_BIT_OR = 0x65 => "COMPOUND_MEMBER_BIT_OR",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_BIT_XOR = 0x66 => "COMPOUND_MEMBER_BIT_XOR",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_SHL = 0x67 => "COMPOUND_MEMBER_SHL",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_SHR = 0x68 => "COMPOUND_MEMBER_SHR",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
COMPOUND_MEMBER_USHR = 0x69 => "COMPOUND_MEMBER_USHR",
def = Some(SlotSpec::Slot(Slot::A)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = true,
// ── 私有 (0x72-0x75) ──
GET_PRIVATE = 0x72 => "GET_PRIVATE", // ext[0]=brand_reg,非 0 才产生 use
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B), SlotSpec::BrandReg],
pure = false, jump = false, term = false, ic = false,
SET_PRIVATE = 0x73 => "SET_PRIVATE",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B), SlotSpec::BrandReg],
pure = false, jump = false, term = false, ic = false,
INIT_PRIVATE = 0x74 => "INIT_PRIVATE",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
PRIVATE_BRAND_IN = 0x75 => "PRIVATE_BRAND_IN",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
// ── 生成器 (0x76-0x78) ──
YIELD = 0x76 => "YIELD", // rd=被让出的值(结果经 reg 0 交付,见 contract.rs)
def = Some(SlotSpec::Reg0), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
// 生成器 body 起点标记:调用时参数初始化完成后挂起于此,首次 next() 从这继续。
SUSPEND_BODY = 0x77 => "SUSPEND_BODY",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
// `yield*` 委托:rd=内层可迭代对象;委托完成值经 reg 0 交付(与 YIELD 同协议)。
YIELD_STAR = 0x78 => "YIELD_STAR",
def = Some(SlotSpec::Reg0), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
// `await`:rd=被等待的值(PromiseResolve 包装);挂起异步帧,恢复值经 reg 0 交付。
AWAIT = 0x79 => "AWAIT",
def = Some(SlotSpec::Reg0), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
// for-await-of 步进:INIT(a=可迭代值) 取异步迭代器;NEXT 调用迭代器 next(),
// 结果写 rd(随后由 AWAIT 等待);DONE 读取 AWAIT 恢复值(a 槽)的 done 写 rd;
// CLOSE 执行异步 IteratorClose(return() 结果 await 后继续)。
FOR_AWAIT_OF_INIT = 0x7A => "FOR_AWAIT_OF_INIT",
def = None, uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
FOR_AWAIT_OF_NEXT = 0x7B => "FOR_AWAIT_OF_NEXT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = false, jump = false, term = false, ic = false,
FOR_AWAIT_OF_DONE = 0x7C => "FOR_AWAIT_OF_DONE",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
FOR_AWAIT_OF_CLOSE = 0x7D => "FOR_AWAIT_OF_CLOSE",
def = None, uses = [],
pure = false, jump = false, term = false, ic = false,
// 无条件新建 cell 并替换 cell_stack[cell_idx],值为 regs[rd]——循环每迭代绑定
// 把当前值拷入新 cell,本迭代闭包捕获新 cell(旧闭包仍指向旧 cell)。
MAKE_CELL_FRESH = 0x7E => "MAKE_CELL_FRESH",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
// 计算键访问器:ext[0]=key 寄存器(`0x8000_0000 | vreg`,低 31 位是 vreg)。
DEFINE_ACCESSOR_DYNAMIC = 0x7F => "DEFINE_ACCESSOR_DYNAMIC",
def = None, uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B), SlotSpec::ExtReg],
pure = false, jump = false, term = false, ic = false,
// ── 位运算 (0x80-0x8F) ──
BIT_AND = 0x80 => "BIT_AND",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
BIT_OR = 0x81 => "BIT_OR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
BIT_XOR = 0x82 => "BIT_XOR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
SHL = 0x83 => "SHL",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
SHR = 0x84 => "SHR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
USHR = 0x85 => "USHR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = false, jump = false, term = false, ic = false,
BIT_NOT = 0x86 => "BIT_NOT",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
TO_OBJECT = 0x87 => "TO_OBJECT", // rd 原地转换(读且写)
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_AND = 0x88 => "COMPOUND_AND",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_OR = 0x89 => "COMPOUND_OR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_XOR = 0x8A => "COMPOUND_XOR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_SHL = 0x8B => "COMPOUND_SHL",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_SHR = 0x8C => "COMPOUND_SHR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
COMPOUND_USHR = 0x8D => "COMPOUND_USHR",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::Rd), SlotSpec::Slot(Slot::A)],
pure = false, jump = false, term = false, ic = false,
NULLISH = 0x8E => "NULLISH",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A), SlotSpec::Slot(Slot::B)],
pure = true, jump = false, term = false, ic = false,
JMP_IF_NULLISH = 0x8F => "JMP_IF_NULLISH",
def = None, uses = [SlotSpec::Slot(Slot::Rd)],
pure = false, jump = true, term = true, ic = false,
// ── 杂项 (0xF0-0xFF) ──
NOP = 0xF0 => "NOP", // 保持 def=Rd:catch-all 使 NOP(rd=None) 的 def_reg=Some(0)
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
HALT = 0xF1 => "HALT", // 隐式读 reg 0(顶层返回值)
def = None, uses = [SlotSpec::Reg0],
pure = false, jump = false, term = true, ic = false,
TYPEOF = 0xF2 => "TYPEOF",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [SlotSpec::Slot(Slot::A)],
pure = true, jump = false, term = false, ic = false,
VOID = 0xF3 => "VOID",
def = Some(SlotSpec::Slot(Slot::Rd)), uses = [],
pure = true, jump = false, term = false, ic = false,
}
/// 4 字节定长指令。
///
/// 布局 `[opcode: u8] [rd: u8] [a: u8] [b: u8]`:
/// - `rd` — 目标寄存器
/// - `a` — 第一个源寄存器,或 imm16 低字节
/// - `b` — 第二个源寄存器,或 imm16 高字节
pub type Instr = u32;
/// 把操作码与三个操作数字节编码为一条 [`Instr`]。
pub fn encode(op: OpCode, rd: u8, a: u8, b: u8) -> Instr {
((b as Instr) << 24) | ((a as Instr) << 16) | ((rd as Instr) << 8) | (op as Instr)
}
/// 解码指令的低 8 位操作码;未知字节返回 [`OpCode::NOP`]。
pub fn opcode(instr: Instr) -> OpCode {
OpCode::try_from((instr & 0xFF) as u8).unwrap_or(OpCode::NOP)
}
/// 解码目标寄存器(bits 8-15)。
pub fn rd(instr: Instr) -> u8 {
((instr >> 8) & 0xFF) as u8
}
/// 解码第一个操作数(bits 16-23)。
pub fn a(instr: Instr) -> u8 {
((instr >> 16) & 0xFF) as u8
}
/// 解码第二个操作数(bits 24-31)。
pub fn b(instr: Instr) -> u8 {
((instr >> 24) & 0xFF) as u8
}
/// 解码 16 位立即数(bits 16-31,由 a、b 两字节拼成)。
pub fn imm16(instr: Instr) -> u16 {
((instr >> 16) & 0xFFFF) as u16
}
/// 解码 16 位有符号跳转偏移(bits 16-31)。
pub fn offset16(instr: Instr) -> i16 {
((instr >> 16) & 0xFFFF) as i16
}
/// 计算 `pc` 处指令之后的扩展字个数(按 opcode 语义推进,逐指令字节序一致)。
///
/// 定长族返回固定字数;变长族依指令内容:spread 调用从首字读 nstatic|nspread、
/// TEMPLATE_STR 从首字读 segment_count、GET_TEMPLATE_OBJECT 从首字读 quasis 段数、
/// CONCAT_N 从首字读操作数总数、NEW_OBJECT 从 a 槽读属性数(键表)。
/// 反汇编 Display 与 IC 清零扫描共用此表,任何新增变长 ext opcode 必须在此登记。
pub fn ext_word_count(bytecode: &[Instr], pc: usize) -> usize {
let op = opcode(bytecode[pc]);
// IC 系固定 IC_EXT_WORDS 扩展字(多态槽组)。
if op.has_ic_ext_words() {
return IC_EXT_WORDS;
}
match op {
OpCode::SPILL
| OpCode::UNSPILL
| OpCode::CALL
| OpCode::CALL_NATIVE
| OpCode::NEW_EXPRESSION
| OpCode::SUPER_CALL
| OpCode::DEFINE_ACCESSOR
| OpCode::DEFINE_ACCESSOR_DYNAMIC
| OpCode::DEFINE_PROP_ATTRS
| OpCode::DEFINE_GLOBAL_PROP_C
| OpCode::DEFINE_GLOBAL_PROP_C_IF_ABSENT
| OpCode::DELETE_GLOBAL_PROP_C
| OpCode::DELETE_PROP_STATIC
| OpCode::REST_OBJECT
| OpCode::INIT_PRIVATE => 1,
OpCode::DEFINE_ACCESSOR_ATTRS
| OpCode::DEFINE_ACCESSOR_ATTRS_DYNAMIC
| OpCode::GET_PRIVATE
| OpCode::SET_PRIVATE
| OpCode::PRIVATE_BRAND_IN => 2,
// 逃出计数 ext:BREAK/CONTINUE/RETURN 恒带 2 个字——第一字
// pack_escape_counts(for-of/for-in 逃出层数打包),第二字 dispose_count
// (逃出资源条数);lower 对这三条无条件落 ext 字,dispatch 经
// read_escape_counts 消费,扫描必须同步跳过以免错位。
OpCode::BREAK | OpCode::CONTINUE | OpCode::RETURN => 2,
OpCode::CALL_SPREAD | OpCode::NEW_EXPRESSION_SPREAD | OpCode::SUPER_CALL_SPREAD => {
let header = bytecode.get(pc + 1).copied().unwrap_or(0);
1 + (header & 0xFF) as usize + ((header >> 8) & 0xFF) as usize
}
OpCode::TEMPLATE_STR => {
let header = bytecode.get(pc + 1).copied().unwrap_or(0);
1 + ((header >> 16) & 0xFFFF) as usize
}
// GET_TEMPLATE_OBJECT:ext[0]=quasis 段数 n,随后 2n 个交错 cooked/raw 字,
// 末尾 1 个 site 序号——总 ext 字数 = 2+2n,与 dispatch 逐字消费一致。
OpCode::GET_TEMPLATE_OBJECT => {
let n = bytecode.get(pc + 1).copied().unwrap_or(0) as usize;
2 + 2 * n
}
// CONCAT_N:ext[0]=n=操作数总数,ext 字数 = 1+(n-1) = n。
OpCode::CONCAT_N => bytecode.get(pc + 1).copied().unwrap_or(0) as usize,
OpCode::NEW_OBJECT => a(bytecode[pc]) as usize,
_ => 0,
}
}
/// 发射无条件跳转指令(`JMP`,偏移以 16 位补码编码)。
pub fn encode_jmp(offset: i16) -> Instr {
let lo = (offset as u16 & 0xFF) as u8;
let hi = ((offset as u16 >> 8) & 0xFF) as u8;
encode(OpCode::JMP, 0, lo, hi)
}
/// 发射 `JMP_IF_FALSE`:当 `rd` 寄存器为 falsy 时跳转。
pub fn encode_jmp_if_false(rd: u8, offset: i16) -> Instr {
let lo = (offset as u16 & 0xFF) as u8;
let hi = ((offset as u16 >> 8) & 0xFF) as u8;
encode(OpCode::JMP_IF_FALSE, rd, lo, hi)
}
/// 发射 `JMP_IF_TRUE`:当 `rd` 寄存器为 truthy 时跳转。
pub fn encode_jmp_if_true(rd: u8, offset: i16) -> Instr {
let lo = (offset as u16 & 0xFF) as u8;
let hi = ((offset as u16 >> 8) & 0xFF) as u8;
encode(OpCode::JMP_IF_TRUE, rd, lo, hi)
}
/// 发射 `JMP_IF_NULLISH`:当 `rd` 为 `null` / `undefined` 时跳转(`??` 短路)。
pub fn encode_jmp_if_nullish(rd: u8, offset: i16) -> Instr {
let lo = (offset as u16 & 0xFF) as u8;
let hi = ((offset as u16 >> 8) & 0xFF) as u8;
encode(OpCode::JMP_IF_NULLISH, rd, lo, hi)
}
/// 发射 `TRY_BEGIN`:标记 try 块开始,偏移指向 catch 处理器。
pub fn encode_try_begin(offset: i16) -> Instr {
let lo = (offset as u16 & 0xFF) as u8;
let hi = ((offset as u16 >> 8) & 0xFF) as u8;
encode(OpCode::TRY_BEGIN, 0, lo, hi)
}
/// 发射 `TRY_FINALLY_BEGIN`:标记 try/finally 块开始,偏移指向 finally 处理器。
pub fn encode_try_finally_begin(offset: i16) -> Instr {
let lo = (offset as u16 & 0xFF) as u8;
let hi = ((offset as u16 >> 8) & 0xFF) as u8;
encode(OpCode::TRY_FINALLY_BEGIN, 0, lo, hi)
}
#[cfg(test)]
mod tests {
use super::*;
/// 遍历全部有效 opcode(枚举字节序)。
fn all_opcodes() -> impl Iterator<Item = OpCode> {
(0u8..=u8::MAX).filter_map(|b| OpCode::try_from(b).ok())
}
#[test]
fn opcode_table_is_byte_identical() {
for byte in 0u8..=u8::MAX {
if let Ok(op) = OpCode::try_from(byte) {
assert_eq!(op as u8, byte, "discriminant mismatch for 0x{byte:02X}");
assert!(!op.to_string().is_empty(), "empty Display for 0x{byte:02X}");
}
}
assert_eq!(OpCode::ADD as u8, 0x00);
assert_eq!(OpCode::STRICT_EQ as u8, 0x1A);
assert_eq!(OpCode::JMP_IF_NULLISH as u8, 0x8F);
assert_eq!(OpCode::VOID as u8, 0xF3);
assert_eq!(OpCode::MOV as u8, 0x0C);
assert_eq!(OpCode::SPILL as u8, 0x0D);
assert_eq!(OpCode::UNSPILL as u8, 0x0E);
assert_eq!(OpCode::SPREAD_OBJECT as u8, 0x0F);
assert_eq!(OpCode::CREATE_ARGUMENTS as u8, 0x63);
assert_eq!(OpCode::CREATE_REST_ARRAY as u8, 0x6E);
assert_eq!(OpCode::DEFINE_ACCESSOR_DYNAMIC as u8, 0x7F);
assert_eq!(OpCode::SET_PROP_BATCH as u8, 0x92);
assert_eq!(OpCode::CONCAT_N as u8, 0x93);
assert_eq!(OpCode::DEFINE_ACCESSOR_ATTRS_DYNAMIC as u8, 0x9F);
assert_eq!(OpCode::ADD.to_string(), "ADD");
assert_eq!(OpCode::COMPOUND_MEMBER_EXP.to_string(), "COMPOUND_MEMBER_EXP");
assert_eq!(OpCode::MOV.to_string(), "MOV");
assert_eq!(OpCode::SPILL.to_string(), "SPILL");
assert_eq!(OpCode::UNSPILL.to_string(), "UNSPILL");
assert_eq!(OpCode::SPREAD_OBJECT.to_string(), "SPREAD_OBJECT");
assert!(OpCode::try_from(0xFA).is_err());
assert!(OpCode::try_from(0xFF).is_err());
}
/// 全 opcode 表遍历:jump/terminator/ic 三集合与 lower/cfg/vm 硬编码集合逐字节一致。
#[test]
fn semantics_golden_sets() {
let jump_set: Vec<u8> = all_opcodes().filter(|op| op.is_jump()).map(|op| op as u8).collect();
assert_eq!(
jump_set,
[0x1E, 0x1F, 0x20, 0x21, 0x22, 0x2F, 0x34, 0x8F],
"is_jump 集合(8 个跳转族,含 TRY_BEGIN/TRY_FINALLY_BEGIN label 回填)"
);
let term_set: Vec<u8> = all_opcodes().filter(|op| op.is_terminator()).map(|op| op as u8).collect();
assert_eq!(
term_set,
[0x1E, 0x1F, 0x20, 0x21, 0x22, 0x2E, 0x41, 0x8F, 0xF1],
"is_terminator 集合(跳转族去 TRY_* 加 RETURN/HALT/THROW)"
);
let ic_set: Vec<u8> = all_opcodes().filter(|op| op.has_ic_ext_words()).map(|op| op as u8).collect();
assert_eq!(ic_set.len(), 16, "ic_ext 恰 16 个");
const _: () = assert!(IC_EXT_WORDS == IC_SLOTS * 2 && IC_SLOTS >= 2);
}
/// 表驱动 ic_ext 与本地冻结的硬编码 16 集合逐项相等(一致性回归,防表驱动改漏)。
#[test]
fn semantics_ic_ext_matches_legacy_list() {
let legacy = [
0x50, 0x51, 0x59, 0x5A, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
];
let tbl: Vec<u8> = all_opcodes().filter(|op| op.has_ic_ext_words()).map(|op| op as u8).collect();
assert_eq!(tbl, legacy);
}
/// ext 字数表与 dispatch 逐字消费布局对齐(定长族 / 双字族 / 变长族)。
#[test]
fn ext_word_count_matches_dispatch_layout() {
// IC 族固定 8 字。
let ic = [encode(OpCode::IC_GET_PROP, 0, 0, 0); IC_EXT_WORDS + 1];
assert_eq!(ext_word_count(&ic, 0), IC_EXT_WORDS);
// 1 字族。
assert_eq!(ext_word_count(&[encode(OpCode::CALL, 0, 0, 0), 3], 0), 1);
// 2 字族(含 BREAK/CONTINUE/RETURN 逃出计数:迭代器打包字 + dispose_count 字)。
assert_eq!(ext_word_count(&[encode(OpCode::BREAK, 0, 0, 0), 1, 2], 0), 2);
assert_eq!(ext_word_count(&[encode(OpCode::RETURN, 0, 0, 0), 1, 2], 0), 2);
assert_eq!(ext_word_count(&[encode(OpCode::GET_PRIVATE, 0, 0, 0), 1, 2], 0), 2);
// 变长族:spread 首字 nstatic|nspread、TEMPLATE_STR 段数、GET_TEMPLATE_OBJECT 2+2n、
// CONCAT_N=n、NEW_OBJECT=a 槽属性数。
assert_eq!(ext_word_count(&[encode(OpCode::CALL_SPREAD, 0, 0, 0), 0x0201, 5, 6, 7], 0), 4);
assert_eq!(ext_word_count(&[encode(OpCode::TEMPLATE_STR, 0, 0, 0), 0x0002_0000, 1, 2], 0), 3);
assert_eq!(ext_word_count(&[encode(OpCode::GET_TEMPLATE_OBJECT, 0, 0, 0), 1, 2, 3, 4], 0), 4);
assert_eq!(ext_word_count(&[encode(OpCode::CONCAT_N, 0, 0, 0), 3, 1, 2], 0), 3);
assert_eq!(ext_word_count(&[encode(OpCode::NEW_OBJECT, 0, 2, 0), 7, 8], 0), 2);
// 无 ext 字。
assert_eq!(ext_word_count(&[encode(OpCode::ADD, 0, 0, 0)], 0), 0);
}
}