perf: 对象字面量批量构造键序预建 shape
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 槽");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user