feat: 新增 DEFINE_ACCESSOR_DYNAMIC opcode 支持计算键对象访问器
This commit is contained in:
@@ -39,6 +39,7 @@ impl Inst {
|
||||
/// - `SpreadArgs`:ext[1..] 每个字 `& 0x7FFF_FFFF`。
|
||||
/// - `TemplateExprs`:ext[1..] 中 `seg>>31==1` 的低 8 位。
|
||||
/// - `BrandReg`:ext[0] 非 0 才产生 use。
|
||||
/// - `ExtReg`:ext[0] `& 0x7FFF_FFFF`(高位标记的寄存器号)。
|
||||
pub fn use_regs(&self) -> SmallVec<[u32; 4]> {
|
||||
let mut uses = SmallVec::new();
|
||||
for &spec in self.op.semantics().uses {
|
||||
@@ -67,6 +68,10 @@ impl Inst {
|
||||
uses.push(brand_reg);
|
||||
}
|
||||
}
|
||||
SlotSpec::ExtReg => {
|
||||
let w = self.ext.first().copied().unwrap_or(0);
|
||||
uses.push(w & 0x7FFF_FFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
uses
|
||||
@@ -418,6 +423,7 @@ mod tests {
|
||||
assert!(!Inst::new(OpCode::SET_PROP, Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)).is_pure(&f));
|
||||
assert!(!Inst::new(OpCode::SUPER_GET_PROP, Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)).is_pure(&f));
|
||||
assert!(!Inst::new(OpCode::DEFINE_ACCESSOR, Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)).is_pure(&f));
|
||||
assert!(!Inst::new(OpCode::DEFINE_ACCESSOR_DYNAMIC, Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)).is_pure(&f));
|
||||
assert!(!Inst::new(OpCode::DELETE_PROP_STATIC, Operand::Reg(0), Operand::Reg(0), Operand::None).is_pure(&f));
|
||||
assert!(!Inst::new(OpCode::DELETE_PROP_DYNAMIC, Operand::Reg(0), Operand::None, Operand::Reg(2)).is_pure(&f));
|
||||
// 调用 / 异常 / 控制流
|
||||
@@ -568,6 +574,9 @@ mod tests {
|
||||
OpCode::DEFINE_ACCESSOR => {
|
||||
Inst::define_accessor(Operand::Reg(1), Operand::Reg(2), Operand::Reg(3), 42)
|
||||
}
|
||||
OpCode::DEFINE_ACCESSOR_DYNAMIC => {
|
||||
Inst::define_accessor_dynamic(Operand::Reg(1), Operand::Reg(2), Operand::Reg(3), 7)
|
||||
}
|
||||
OpCode::DELETE_PROP_STATIC => Inst::delete_prop_static(Operand::Reg(1), 9),
|
||||
_ => Inst::new(op, Operand::Reg(1), Operand::Reg(2), Operand::Reg(3)),
|
||||
}
|
||||
@@ -740,6 +749,7 @@ mod tests {
|
||||
assert_group(&[OpCode::SUPER_GET_PROP, OpCode::SUPER_STATIC_GET_PROP], Some(1), &[2, 3], false);
|
||||
assert_contract(OpCode::SET_HOME_OBJECT, None, &[1, 2], false);
|
||||
assert_contract(OpCode::DEFINE_ACCESSOR, None, &[1, 2, 3], false);
|
||||
assert_contract(OpCode::DEFINE_ACCESSOR_DYNAMIC, None, &[1, 2, 3, 7], false);
|
||||
// Object Property:GET_PROP 写 a 槽、DYNAMIC 写 b 槽
|
||||
assert_contract(OpCode::GET_PROP, Some(2), &[1, 3], false);
|
||||
assert_contract(OpCode::GET_PROP_DYNAMIC, Some(3), &[1, 2], false);
|
||||
|
||||
@@ -199,6 +199,12 @@ impl Inst {
|
||||
Self::with_ext(OpCode::DEFINE_ACCESSOR, home, get, set, &[key_idx])
|
||||
}
|
||||
|
||||
/// 定义访问器属性(运行时计算键):home 为宿主对象,get/set 为访问器函数寄存器,
|
||||
/// key_reg 为键值寄存器(编码进 ext[0],高位标记 `0x8000_0000 | key_reg`)。
|
||||
pub fn define_accessor_dynamic(home: Operand, get: Operand, set: Operand, key_reg: u32) -> Self {
|
||||
Self::with_ext(OpCode::DEFINE_ACCESSOR_DYNAMIC, home, get, set, &[0x8000_0000 | key_reg])
|
||||
}
|
||||
|
||||
/// define 数据属性:target 为宿主对象,value/key 为寄存器。
|
||||
/// 不触发原型链 setter,与 SET_PROP 语义不同。
|
||||
pub fn define_prop(target: Operand, value: Operand, key: Operand) -> Self {
|
||||
@@ -428,6 +434,13 @@ mod tests {
|
||||
assert_eq!(accessor.a, Operand::Reg(1));
|
||||
assert_eq!(accessor.b, Operand::Reg(2));
|
||||
|
||||
let dyn_accessor = Inst::define_accessor_dynamic(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2), 7);
|
||||
assert_eq!(dyn_accessor.op, OpCode::DEFINE_ACCESSOR_DYNAMIC);
|
||||
assert_eq!(dyn_accessor.ext.as_slice(), &[0x8000_0000 | 7]);
|
||||
assert_eq!(dyn_accessor.rd, Operand::Reg(0));
|
||||
assert_eq!(dyn_accessor.a, Operand::Reg(1));
|
||||
assert_eq!(dyn_accessor.b, Operand::Reg(2));
|
||||
|
||||
let rest = Inst::rest_object(Operand::Reg(0), Operand::Reg(1), 7, None);
|
||||
assert_eq!(rest.ext.as_slice(), &[7]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user