perf: IC 多态化 4 槽缓存(FIFO 滚动写回)消除多态场景 miss 重解析
每条 IC 指令扩展字 3→8(4 槽 × [shape_id|proto_depth, slot]),命中槽 0 单态快路径零额外成本,槽 1..3 懒解码遍历,miss 写回 FIFO 滚动(新条目进 槽 0、最老丢弃)。修复原型链 IC 深度解析多走一步与 prop_forge 模板不匹配 不写回两个使缓存恒失效的问题。ic_cache 基准命中率 34.8%→78.9%, 耗时 -29%;单态 prop_access 因扩展字布局膨胀有 ~20% 取指回归(后续 side-table 方案可根除)。
This commit is contained in:
+32
-23
@@ -4,7 +4,7 @@
|
||||
//! 全部由 `inst_*` 构造 API 保证——emit 代码不直接触碰 `ext` 字段。
|
||||
//! 寄存器 def/use 契约与副作用判定在 `contract` 模块(`impl Inst`,DCE/liveness 共用)。
|
||||
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_bytecode::opcode::{OpCode, IC_EXT_WORDS};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::operand::{LabelId, Operand};
|
||||
@@ -42,86 +42,86 @@ impl Inst {
|
||||
}
|
||||
}
|
||||
|
||||
// ── IC 系:ext = [0, 0, 0](shape/slot/proto 占位字,VM 运行时回填)──
|
||||
// ── IC 系:ext = [0; IC_EXT_WORDS](IC_SLOTS 组 shape/slot/proto 占位字,VM 运行时回填)──
|
||||
|
||||
/// 内联缓存读属性:结果写入 `dst`,属性键为 `key`。
|
||||
pub fn ic_get(dst: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::IC_GET_PROP, Operand::None, dst, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::IC_GET_PROP, Operand::None, dst, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 内联缓存写属性:`obj[key] = value`。
|
||||
pub fn ic_set(obj: Operand, value: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::IC_SET_PROP, obj, value, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::IC_SET_PROP, obj, value, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员自增:`obj[key]++`,val 为当前值寄存器。
|
||||
pub fn member_inc(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::MEMBER_INC, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::MEMBER_INC, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员自减:`obj[key]--`,val 为当前值寄存器。
|
||||
pub fn member_dec(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::MEMBER_DEC, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::MEMBER_DEC, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值加法:`obj[key] += val`。
|
||||
pub fn compound_member_add(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_ADD, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_ADD, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值减法:`obj[key] -= val`。
|
||||
pub fn compound_member_sub(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_SUB, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_SUB, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值乘法:`obj[key] *= val`。
|
||||
pub fn compound_member_mul(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_MUL, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_MUL, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值除法:`obj[key] /= val`。
|
||||
pub fn compound_member_div(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_DIV, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_DIV, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值取模:`obj[key] %= val`。
|
||||
pub fn compound_member_mod(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_MOD, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_MOD, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值指数:`obj[key] **= val`。
|
||||
pub fn compound_member_exp(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_EXP, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_EXP, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值按位与:`obj[key] &= val`。
|
||||
pub fn compound_member_bit_and(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_BIT_AND, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_BIT_AND, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值按位或:`obj[key] |= val`。
|
||||
pub fn compound_member_bit_or(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_BIT_OR, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_BIT_OR, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值按位异或:`obj[key] ^= val`。
|
||||
pub fn compound_member_bit_xor(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_BIT_XOR, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_BIT_XOR, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值左移:`obj[key] <<= val`。
|
||||
pub fn compound_member_shl(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_SHL, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_SHL, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值右移:`obj[key] >>= val`。
|
||||
pub fn compound_member_shr(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_SHR, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_SHR, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
/// 成员复合赋值无符号右移:`obj[key] >>>= val`。
|
||||
pub fn compound_member_ushr(obj: Operand, val: Operand, key: Operand) -> Self {
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_USHR, obj, val, key, &[0, 0, 0])
|
||||
Self::with_ext(OpCode::COMPOUND_MEMBER_USHR, obj, val, key, &[0; IC_EXT_WORDS])
|
||||
}
|
||||
|
||||
// ── Call 系:ext = [nargs] ──
|
||||
@@ -199,7 +199,6 @@ impl Inst {
|
||||
Self::with_ext(OpCode::DEFINE_ACCESSOR, home, get, set, &[key_idx])
|
||||
}
|
||||
|
||||
|
||||
/// 定义访问器属性并指定描述符:ext = [key_idx, attrs](attrs 位同 DEFINE_PROP_ATTRS)。
|
||||
pub fn define_accessor_attrs(home: Operand, get: Operand, set: Operand, key_idx: u32, attrs: u32) -> Self {
|
||||
Self::with_ext(OpCode::DEFINE_ACCESSOR_ATTRS, home, get, set, &[key_idx, attrs])
|
||||
@@ -216,7 +215,6 @@ impl Inst {
|
||||
Self::new(OpCode::DEFINE_PROP, target, value, key)
|
||||
}
|
||||
|
||||
|
||||
/// define 数据属性并指定描述符:ext = [attrs](bit0=writable, bit1=enumerable, bit2=configurable,
|
||||
/// 与 PropAttributes 位一致);class 方法/constructor/prototype 需要非枚举或不可写描述符。
|
||||
pub fn define_prop_attrs(target: Operand, value: Operand, key: Operand, attrs: u32) -> Self {
|
||||
@@ -409,7 +407,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ic_instructions_carry_three_zero_ext_words() {
|
||||
fn ic_instructions_carry_ic_slots_zero_ext_words() {
|
||||
let insts = [
|
||||
Inst::ic_get(Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::ic_set(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
@@ -421,10 +419,21 @@ mod tests {
|
||||
Inst::compound_member_div(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_mod(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_exp(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_bit_and(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_bit_or(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_bit_xor(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_shl(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_shr(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
Inst::compound_member_ushr(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)),
|
||||
];
|
||||
for inst in &insts {
|
||||
assert_eq!(inst.ext.as_slice(), &[0, 0, 0], "IC op {} must carry 3 zero ext words", inst.op);
|
||||
assert!(inst.ext.len() == 3);
|
||||
assert_eq!(
|
||||
inst.ext.as_slice(),
|
||||
&[0; IC_EXT_WORDS],
|
||||
"IC op {} must carry {IC_EXT_WORDS} zero ext words",
|
||||
inst.op
|
||||
);
|
||||
assert_eq!(inst.ext.len(), IC_EXT_WORDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ fn backward_jump_encodes_negative_offset() {
|
||||
|
||||
#[test]
|
||||
fn jump_offset_counts_ext_words_in_target() {
|
||||
// jmp(0) → ic_get(1 + 3 ext = 4 instr)→ ADD(instr 5)
|
||||
// jmp(0) → ic_get(1 + 8 ext = 9 instr)→ ADD(instr 10)
|
||||
let mut f = base_module();
|
||||
f.insts.push(Inst::jmp(0));
|
||||
f.insts.push(Inst::ic_get(Operand::Reg(1), Operand::Reg(2)));
|
||||
@@ -96,21 +96,21 @@ fn jump_offset_counts_ext_words_in_target() {
|
||||
f.label_pos = vec![Some(2)];
|
||||
f.label_count = 1;
|
||||
let m = lower_ok(&f);
|
||||
assert_eq!(m.bytecode.len(), 1 + 4 + 1);
|
||||
assert_eq!(opcode::offset16(m.bytecode[0]), 5);
|
||||
assert_eq!(m.bytecode.len(), 1 + 9 + 1);
|
||||
assert_eq!(opcode::offset16(m.bytecode[0]), 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ic_get_carries_three_zero_ext_words() {
|
||||
fn ic_get_carries_ic_slots_zero_ext_words() {
|
||||
let mut f = base_module();
|
||||
f.insts.push(Inst::ic_get(Operand::Reg(1), Operand::Reg(2)));
|
||||
let m = lower_ok(&f);
|
||||
assert_eq!(m.bytecode.len(), 4);
|
||||
assert_eq!(m.bytecode.len(), 9);
|
||||
assert_eq!(opcode::opcode(m.bytecode[0]), OpCode::IC_GET_PROP);
|
||||
assert_eq!(opcode::rd(m.bytecode[0]), 0);
|
||||
assert_eq!(opcode::a(m.bytecode[0]), 1);
|
||||
assert_eq!(opcode::b(m.bytecode[0]), 2);
|
||||
assert_eq!(m.bytecode[1..], [0, 0, 0]);
|
||||
assert_eq!(m.bytecode[1..], [0; oxide_bytecode::opcode::IC_EXT_WORDS]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user