pub trait JitExtension: Send + Sync {
fn can_jit(&self, ext_id: u16) -> bool;
fn op_count(&self) -> usize;
fn name(&self) -> &str;
}
pub struct NativeCode {
_private: (),
}
pub struct JitCompiler {
extensions: Vec<Box<dyn JitExtension>>,
}
impl JitCompiler {
pub fn new() -> Self {
Self {
extensions: Vec::new(),
}
}
pub fn register_extension(&mut self, ext: Box<dyn JitExtension>) {
tracing::info!(
name = ext.name(),
ops = ext.op_count(),
"JIT extension registered"
);
self.extensions.push(ext);
}
pub fn is_eligible(&self, chunk: &crate::Chunk) -> bool {
use crate::Op;
for op in &chunk.ops {
match op {
Op::Nop
| Op::LoadInt(_) | Op::LoadFloat(_) | Op::LoadConst(_)
| Op::LoadTrue | Op::LoadFalse | Op::LoadUndef
| Op::Pop | Op::Dup | Op::Dup2 | Op::Swap | Op::Rot
| Op::GetVar(_) | Op::SetVar(_) | Op::DeclareVar(_)
| Op::GetSlot(_) | Op::SetSlot(_)
| Op::Add | Op::Sub | Op::Mul | Op::Div | Op::Mod | Op::Pow
| Op::Negate | Op::Inc | Op::Dec
| Op::Concat | Op::StringRepeat | Op::StringLen
| Op::NumEq | Op::NumNe | Op::NumLt | Op::NumGt | Op::NumLe | Op::NumGe
| Op::StrEq | Op::StrNe | Op::StrLt | Op::StrGt | Op::StrLe | Op::StrGe
| Op::StrCmp | Op::Spaceship
| Op::LogNot | Op::LogAnd | Op::LogOr
| Op::BitAnd | Op::BitOr | Op::BitXor | Op::BitNot | Op::Shl | Op::Shr
| Op::Jump(_) | Op::JumpIfTrue(_) | Op::JumpIfFalse(_)
| Op::JumpIfTrueKeep(_) | Op::JumpIfFalseKeep(_)
| Op::Call(_, _) | Op::Return | Op::ReturnValue
| Op::PushFrame | Op::PopFrame
| Op::PreIncSlot(_) | Op::PreIncSlotVoid(_)
| Op::SlotLtIntJumpIfFalse(_, _, _)
| Op::SlotIncLtIntJumpBack(_, _, _)
| Op::AccumSumLoop(_, _, _)
| Op::AddAssignSlotVoid(_, _)
| Op::SetStatus | Op::GetStatus => continue,
Op::Extended(id, _) | Op::ExtendedWide(id, _) => {
let id = *id;
if !self.extensions.iter().any(|ext| ext.can_jit(id)) {
return false;
}
}
_ => return false,
}
}
true
}
}
impl Default for JitCompiler {
fn default() -> Self {
Self::new()
}
}