Broken site based impl

This commit is contained in:
2026-10-03 14:06:24 +00:00
parent 23a2c3bc46
commit 44498b32a9
39 changed files with 4250 additions and 1750 deletions
+71
View File
@@ -0,0 +1,71 @@
use super::{ENV_ARG, PROTO_FIELD, pusher};
use crate::{
libqjs::parse::{Atom, ImmOperand, Instr, JsValue, opcodes::OpCode},
native,
};
/// Replace ops that are a fixed sequence of simpler ones
///
/// A sequence is never empty: jumps find their target by its pc (see regify),
/// so every instr must keep at least one instr at its pc
pub fn replace_expansion(instr: &Instr, out: &mut Vec<Instr>) -> bool {
use OpCode::*;
let none = ImmOperand::None;
let imm = instr.imm;
// A plain call has no `this`, so it passes `undefined`. It is pushed last,
// on top of the args, and the call pops it as one more arg (see regify)
let plain_call = |n: u16| [(Undefined, none), (Call, ImmOperand::Npop(n + 1))];
let tail_call = |n: u16| [(Undefined, none), (Call, ImmOperand::Npop(n + 1)), (Return, none)];
let seq: &[(OpCode, ImmOperand)] = match (instr.op, imm) {
(Call0, _) => &plain_call(0),
(Call1, _) => &plain_call(1),
(Call2, _) => &plain_call(2),
(Call3, _) => &plain_call(3),
(Call, ImmOperand::Npop(n)) => &plain_call(n),
(TailCall, ImmOperand::Npop(n)) => &tail_call(n),
(TailCallMethod, _) => &[(CallMethod, imm), (Return, none)],
(GetField2, _) => &[(Dup, none), (GetField, imm)],
(GetLoc0Loc1, _) => &[(GetLoc0, none), (GetLoc1, none)],
(IncLoc, _) => &[(GetLoc, imm), (Inc, none), (PutLoc, imm)],
(DecLoc, _) => &[(GetLoc, imm), (Dec, none), (PutLoc, imm)],
// The added value is on the stack, the local is the left operand
(AddLoc, _) => &[(GetLoc, imm), (Swap, none), (Add, none), (PutLoc, imm)],
(SetProto, _) => &[(DefineField, ImmOperand::Atom(PROTO_FIELD))],
// The low two bits of `arg`: 0 method, 1 getter, 2 setter
(DefineMethod, ImmOperand::AtomU8 { atom, arg }) => {
assert!(arg & 3 == 0, "getters and setters are not supported");
&[(DefineField, ImmOperand::Atom(atom))]
}
// The fn itself, which is its env
(SpecialObject, ImmOperand::U8(2)) => &[(GetArg, ImmOperand::Arg(ENV_ARG))],
// [[HomeObject]], which only `super` reads. `super` is not supported
// (see set_home_object in regify)
(SpecialObject, ImmOperand::U8(4)) => &[(Undefined, none)],
// arguments, new.target, import.meta
(SpecialObject, _) => unimplemented!("special_object {imm:?}"),
_ => return false,
};
let mut push = pusher(instr.pc, out);
seq.iter().for_each(|&(op, imm)| push(op, imm));
true
}
/// Replace a read of a global with the constant it is (see `native`)
pub fn replace_get_var(
instr: &Instr,
atoms: &[Atom],
cpool: &mut Vec<JsValue>,
out: &mut Vec<Instr>,
) -> bool {
if instr.op != OpCode::GetVar {
return false;
}
cpool.push(native::global(instr.imm.atom(), atoms));
pusher(instr.pc, out)(OpCode::PushConst, ImmOperand::Const(cpool.len() as u32 - 1));
true
}