Misc cleanups

This commit is contained in:
UditDey
2026-09-28 07:47:01 +00:00
parent e93ce94ac7
commit a4d295fbd9
18 changed files with 563 additions and 1388 deletions
+46 -40
View File
@@ -14,50 +14,13 @@ pub struct FlatFn {
pub fn flatten(bin: QuickJSBinary) -> (Vec<FlatFn>, Vec<Vec<ClosureVar>>, Vec<Atom>) {
let mut fns = vec![];
let mut captures = vec![];
walk(bin.root_mod.root_fn, &mut fns, &mut captures);
append_entry(&mut fns, &mut captures);
add_entry_point(&mut fns, &mut captures);
(fns, captures, bin.atoms)
}
/// Append the synthetic program entry, the host the runtime would provide,
/// written in the IR so the ordinary passes handle it. It drives the module
/// body `<eval>` (fn 0): build its environment record, run the link phase
/// (`this = true`), then the evaluate phase (`this = false`).
///
/// `fclosure8` of fn 0 lets `declosure` build the record from `<eval>`'s own
/// captures — the module bindings — so no stage needs bespoke module knowledge.
/// The closure is made once and kept in local 0, so both phases run on the one
/// record and the link phase's writes reach the evaluate phase. `call_method`
/// carries the phase flag as the receiver (`this`); a plain call could not set
/// it.
fn append_entry(fns: &mut Vec<FlatFn>, captures: &mut Vec<Vec<ClosureVar>>) {
let mk = |pc, op, imm| Instr { pc, op, imm };
let code = vec![
mk(0, OpCode::Fclosure8, ImmOperand::Const(0)),
mk(1, OpCode::PutLoc, ImmOperand::Loc(0)),
mk(2, OpCode::PushTrue, ImmOperand::None),
mk(3, OpCode::GetLoc, ImmOperand::Loc(0)),
mk(4, OpCode::CallMethod, ImmOperand::Npop(0)),
mk(5, OpCode::Drop, ImmOperand::None),
mk(6, OpCode::PushFalse, ImmOperand::None),
mk(7, OpCode::GetLoc, ImmOperand::Loc(0)),
mk(8, OpCode::CallMethod, ImmOperand::Npop(0)),
mk(9, OpCode::Drop, ImmOperand::None),
mk(10, OpCode::ReturnUndef, ImmOperand::None),
];
fns.push(FlatFn {
name: AtomRef::Predefined(0),
arg_count: 0,
// Local 0 holds the closure of `<eval>`.
var_count: 1,
cpool: vec![JsValue::FnById(0)],
code,
});
captures.push(vec![]);
}
fn walk(func: Function, flat_fns: &mut Vec<FlatFn>, captures: &mut Vec<Vec<ClosureVar>>) -> usize {
let id = flat_fns.len();
@@ -83,3 +46,46 @@ fn walk(func: Function, flat_fns: &mut Vec<FlatFn>, captures: &mut Vec<Vec<Closu
flat_fns[id].cpool = cpool;
id
}
/// Add our synthetic entry point, equivalent to:
/// ```js
/// function <null>() {
/// // Module top level <eval> created by quickjs
/// // All other top level decls are inside <eval>
/// function <eval>() {
/// ...
/// }
///
/// <eval>.call(true); // Link phase (`this = true`)
/// <eval>.call(false); // Run phase (`this = false`)
/// }
/// ```
///
/// This gets called by C main()
fn add_entry_point(fns: &mut Vec<FlatFn>, captures: &mut Vec<Vec<ClosureVar>>) {
let instr = |pc, op, imm| Instr { pc, op, imm };
let code = vec![
instr(0, OpCode::Fclosure8, ImmOperand::Const(0)),
instr(1, OpCode::PutLoc, ImmOperand::Loc(0)),
instr(2, OpCode::PushTrue, ImmOperand::None),
instr(3, OpCode::GetLoc, ImmOperand::Loc(0)),
instr(4, OpCode::CallMethod, ImmOperand::Npop(0)),
instr(5, OpCode::Drop, ImmOperand::None),
instr(6, OpCode::PushFalse, ImmOperand::None),
instr(7, OpCode::GetLoc, ImmOperand::Loc(0)),
instr(8, OpCode::CallMethod, ImmOperand::Npop(0)),
instr(9, OpCode::Drop, ImmOperand::None),
instr(10, OpCode::ReturnUndef, ImmOperand::None),
];
fns.push(FlatFn {
name: AtomRef::Predefined(0),
arg_count: 0,
var_count: 1,
cpool: vec![JsValue::FnById(0)],
code,
});
captures.push(vec![]);
}