perf: 对象字面量批量构造键序预建 shape

This commit is contained in:
2026-08-14 04:47:15 +08:00
parent 9758cee544
commit 12ebdb8c0e
11 changed files with 395 additions and 24 deletions
+2
View File
@@ -756,6 +756,8 @@ mod tests {
assert_contract(OpCode::IC_GET_PROP, Some(1), &[1, 2], false);
assert_contract(OpCode::SET_PROP, None, &[1, 2, 3], false);
assert_contract(OpCode::SET_PROP_DYNAMIC, None, &[1, 2, 3], false);
// SET_PROP_BATCH:b 槽是 Imm(slot) 非寄存器,canonical 构造下仍按槽位读。
assert_contract(OpCode::SET_PROP_BATCH, None, &[1, 2, 3], false);
assert_contract(OpCode::IC_SET_PROP, None, &[1, 2, 3], false);
assert_contract(OpCode::SET_ELEM, None, &[1, 2, 3], false);
assert_group(&[OpCode::NEW_OBJECT, OpCode::NEW_ARRAY], Some(1), &[], true);
+13
View File
@@ -247,6 +247,19 @@ impl Inst {
Self::new(OpCode::SPREAD_OBJECT, target, src, Operand::None)
}
/// 对象字面量批量构造:`dst` 为新对象,a 槽编码纯静态数据键前缀的属性数(≤255),
/// ext 为每键的常量池下标(`Constant::String`)。运行时按键序链式预建 shape,
/// 后续逐个 `SET_PROP_BATCH` 纯槽写。
pub fn new_object(dst: Operand, nprops: u32, key_idxs: &[u32]) -> Self {
Self::with_ext(OpCode::NEW_OBJECT, dst, Operand::Imm(nprops as u16), Operand::None, key_idxs)
}
/// 对象字面量批量构造的纯槽写:`target[slot] = value`。slot 对应键序预建 shape 的槽位,
/// 不做键解析/形状变更。
pub fn set_prop_batch(target: Operand, value: Operand, slot: u16) -> Self {
Self::new(OpCode::SET_PROP_BATCH, target, value, Operand::Imm(slot))
}
/// TEMPLATE_STR:变长 ext。首字打包 `(segment_count<<16) | total_len_hint`,
/// 后续每 quasi 一项 `quasi_const_idx & 0x7FFF_FFFF`,其后若跟表达式再一项 `0x8000_0000 | expr_reg`。
pub fn template_str(dst: Operand, segment_count: u32, total_len_hint: u16, parts: &[u32]) -> Self {
+38
View File
@@ -307,3 +307,41 @@ fn operand_this_is_semantic_not_physical_index() {
assert_eq!(Operand::This, Operand::This);
assert_eq!(Operand::NewTarget, Operand::NewTarget);
}
#[test]
fn new_object_batch_carries_nprops_and_key_table() {
// NEW_OBJECT(a=Imm(2)) → 2 个键常量 ext 字;键序即 shape 槽序。
let mut f = base_module();
f.insts.push(Inst::new_object(Operand::Reg(1), 2, &[10, 11]));
let m = lower_ok(&f);
assert_eq!(m.bytecode.len(), 3);
assert_eq!(opcode::opcode(m.bytecode[0]), OpCode::NEW_OBJECT);
assert_eq!(opcode::rd(m.bytecode[0]), 1);
assert_eq!(opcode::a(m.bytecode[0]), 2, "a 槽编码属性数");
assert_eq!(opcode::b(m.bytecode[0]), 0, "nprops ≤255 时高字节为 0");
assert_eq!(m.bytecode[1], 10);
assert_eq!(m.bytecode[2], 11);
}
#[test]
fn new_object_zero_props_has_no_ext_words() {
// 空字面量 {} 仍发 0 属性数 NEW_OBJECT,无键表。
let mut f = base_module();
f.insts.push(Inst::new_object(Operand::Reg(1), 0, &[]));
let m = lower_ok(&f);
assert_eq!(m.bytecode.len(), 1);
assert_eq!(opcode::opcode(m.bytecode[0]), OpCode::NEW_OBJECT);
assert_eq!(opcode::a(m.bytecode[0]), 0);
}
#[test]
fn set_prop_batch_encodes_slot_imm_in_b() {
let mut f = base_module();
f.insts.push(Inst::set_prop_batch(Operand::Reg(1), Operand::Reg(2), 3));
let m = lower_ok(&f);
assert_eq!(m.bytecode.len(), 1);
assert_eq!(opcode::opcode(m.bytecode[0]), OpCode::SET_PROP_BATCH);
assert_eq!(opcode::rd(m.bytecode[0]), 1);
assert_eq!(opcode::a(m.bytecode[0]), 2);
assert_eq!(opcode::b(m.bytecode[0]), 3, "slot 编码进 b 槽");
}