Misc cleanups
This commit is contained in:
+46
-40
@@ -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![]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user