feat: 调用实参 spread(f(...args) / new F(...args) / super(...args))

This commit is contained in:
2026-08-08 10:33:16 +08:00
parent 8354befb63
commit ab979dc47b
14 changed files with 811 additions and 140 deletions
+41 -1
View File
@@ -18,7 +18,7 @@ impl Inst {
pub fn def_reg(&self) -> Option<u32> {
match self.op {
// CALL 系:结果隐式写 reg 0,rd 是 callee 的 use
OpCode::CALL | OpCode::CALL_NATIVE => Some(0),
OpCode::CALL | OpCode::CALL_NATIVE | OpCode::CALL_SPREAD => Some(0),
// GET_PROP 系:结果写 a/b 槽而非 rd
OpCode::GET_PROP | OpCode::IC_GET_PROP => reg_of(&self.a),
OpCode::GET_PROP_DYNAMIC => reg_of(&self.b),
@@ -91,6 +91,25 @@ impl Inst {
let nargs = self.ext.first().copied().unwrap_or(0);
push_range(&mut uses, reg_of(&self.a), nargs);
}
// spread 调用系:ext 内嵌有序实参字(静态寄存器号 / `0x8000_0000|reg` spread 源)
OpCode::CALL_SPREAD => {
push_operand(&mut uses, &self.rd);
push_operand(&mut uses, &self.a);
for &w in self.ext.iter().skip(1) {
uses.push(w & 0x7FFF_FFFF);
}
}
OpCode::NEW_EXPRESSION_SPREAD => {
push_operand(&mut uses, &self.a);
for &w in self.ext.iter().skip(1) {
uses.push(w & 0x7FFF_FFFF);
}
}
OpCode::SUPER_CALL_SPREAD => {
for &w in self.ext.iter().skip(1) {
uses.push(w & 0x7FFF_FFFF);
}
}
// GET_PROP 系:结果写 a/b 槽,rd=obj 是 use
OpCode::GET_PROP => {
push_operand(&mut uses, &self.rd);
@@ -435,6 +454,24 @@ mod tests {
assert_eq!(inst.use_regs().as_slice(), &[0]);
}
#[test]
fn spread_call_def_and_uses() {
// CALL_SPREAD:结果隐式写 reg 0;use = callee + this + ext 有序实参字(静态/spread 同编)
let call = Inst::call_spread(Operand::Reg(0), Operand::Reg(1), &[5, 0x8000_0000 | 9, 300]);
assert_eq!(call.def_reg(), Some(0));
assert_eq!(call.use_regs().as_slice(), &[0, 1, 5, 9, 300]);
// NEW_EXPRESSION_SPREAD:rd 即 def;use = ctor + 实参字
let ne = Inst::new_expression_spread(Operand::Reg(3), Operand::Reg(0), &[7, 0x8000_0000 | 12]);
assert_eq!(ne.def_reg(), Some(3));
assert_eq!(ne.use_regs().as_slice(), &[0, 7, 12]);
// SUPER_CALL_SPREAD:无 callee/this 槽
let sc = Inst::super_call_spread(Operand::Reg(3), &[4, 0x8000_0000 | 8]);
assert_eq!(sc.def_reg(), Some(3));
assert_eq!(sc.use_regs().as_slice(), &[4, 8]);
}
#[test]
fn void_defs_rd_no_use() {
// VM 的 VOID handler 不读 a 槽
@@ -630,6 +667,9 @@ mod tests {
assert!(!Inst::call_native(Operand::Reg(0), Operand::Reg(1), Operand::Reg(2), 0).is_pure(&f));
assert!(!Inst::new_expression(Operand::Reg(3), Operand::Reg(0), Operand::Reg(1), 0).is_pure(&f));
assert!(!Inst::super_call(Operand::Reg(3), Operand::Reg(1), 0).is_pure(&f));
assert!(!Inst::call_spread(Operand::Reg(0), Operand::Reg(1), &[3]).is_pure(&f));
assert!(!Inst::new_expression_spread(Operand::Reg(3), Operand::Reg(0), &[2]).is_pure(&f));
assert!(!Inst::super_call_spread(Operand::Reg(3), &[2]).is_pure(&f));
assert!(!Inst::new(OpCode::CREATE_REGEXP, Operand::Reg(0), Operand::Reg(1), Operand::Reg(2)).is_pure(&f));
assert!(!Inst::new(OpCode::RETURN, Operand::None, Operand::None, Operand::None).is_pure(&f));
assert!(!Inst::new(OpCode::THROW, Operand::Reg(2), Operand::None, Operand::None).is_pure(&f));
+54
View File
@@ -116,6 +116,26 @@ impl Inst {
Self::with_ext(OpCode::SUPER_CALL, result, first_arg, Operand::None, &[nargs as u32])
}
/// spread 实参调用:rd=callee,a=this,b 槽未用。
/// ext=[nstatic|(nspread<<8), 有序实参字…];每个实参字:静态实参为寄存器号,
/// spread 源为 `0x8000_0000 | 寄存器号`(高位标记),按源码求值序排列。
pub fn call_spread(callee: Operand, this: Operand, words: &[u32]) -> Self {
let ext = spread_ext(words);
Self::with_ext(OpCode::CALL_SPREAD, callee, this, Operand::None, &ext)
}
/// spread 实参 `new`:结果写入 `result`,构造函数为 `constructor`。
pub fn new_expression_spread(result: Operand, constructor: Operand, words: &[u32]) -> Self {
let ext = spread_ext(words);
Self::with_ext(OpCode::NEW_EXPRESSION_SPREAD, result, constructor, Operand::None, &ext)
}
/// 派生类构造中的 `super(...spread)`:结果写入 `result`。
pub fn super_call_spread(result: Operand, words: &[u32]) -> Self {
let ext = spread_ext(words);
Self::with_ext(OpCode::SUPER_CALL_SPREAD, result, Operand::None, Operand::None, &ext)
}
// ── 其他带 ext 字 ──
/// 定义访问器属性:home 为宿主对象,get/set 为访问器函数寄存器,key_idx 为属性名常量下标。
@@ -217,6 +237,17 @@ impl Inst {
}
}
/// spread 调用系 ext 构造:首字打包 `nstatic | (nspread << 8)`,后续按源码求值序排列
/// 每个实参字(静态实参 = 寄存器号,spread 源 = `0x8000_0000 | 寄存器号`)。
fn spread_ext(words: &[u32]) -> SmallVec<[u32; 4]> {
let nspread = words.iter().filter(|w| *w >> 31 == 1).count() as u32;
let nstatic = (words.len() as u32) - nspread;
let mut ext = SmallVec::with_capacity(1 + words.len());
ext.push(nstatic | (nspread << 8));
ext.extend_from_slice(words);
ext
}
#[cfg(test)]
mod tests {
use super::*;
@@ -282,6 +313,29 @@ mod tests {
assert_eq!(rest.ext.as_slice(), &[7]);
}
#[test]
fn spread_call_constructors_carry_header_and_source_regs() {
let call = Inst::call_spread(Operand::Reg(0), Operand::Reg(1), &[10, 0x8000_0000 | 300]);
assert_eq!(call.op, OpCode::CALL_SPREAD);
assert_eq!(call.rd, Operand::Reg(0));
assert_eq!(call.a, Operand::Reg(1));
assert_eq!(call.b, Operand::None);
assert_eq!(call.ext.as_slice(), &[1 | (1 << 8), 10, 0x8000_0000 | 300]);
let ne = Inst::new_expression_spread(Operand::Reg(3), Operand::Reg(0), &[0x8000_0000 | 7]);
assert_eq!(ne.op, OpCode::NEW_EXPRESSION_SPREAD);
assert_eq!(ne.rd, Operand::Reg(3));
assert_eq!(ne.a, Operand::Reg(0));
assert_eq!(ne.ext.as_slice(), &[1 << 8, 0x8000_0000 | 7]);
let sc = Inst::super_call_spread(Operand::Reg(3), &[1, 0x8000_0000 | 5]);
assert_eq!(sc.op, OpCode::SUPER_CALL_SPREAD);
assert_eq!(sc.rd, Operand::Reg(3));
assert_eq!(sc.a, Operand::None);
assert_eq!(sc.b, Operand::None);
assert_eq!(sc.ext.as_slice(), &[1 | (1 << 8), 1, 0x8000_0000 | 5]);
}
#[test]
fn regalloc_constructors_carry_expected_slots() {
let mov = Inst::inst_mov(Operand::Reg(3), Operand::Reg(7));