use crate::runtime::heap::{Gc, GcHeader, Marker};
use crate::runtime::string::LuaStr;
use crate::runtime::value::Value;
use crate::vm::isa::Inst;
#[derive(Clone, Copy)]
pub struct Frame {
pub closure: Gc<LuaClosure>,
pub base: u32,
pub pc: u32,
pub func_slot: u32,
pub n_varargs: u32,
pub nresults: i32,
pub hook_oldpc: u32,
pub from_c: bool,
pub tm: Option<&'static str>,
pub is_hook: bool,
pub tailcalls: u32,
}
#[derive(Clone, Copy)]
pub enum CallFrame {
Lua(
Frame,
),
Cont(
NativeCont,
),
}
impl CallFrame {
#[inline]
pub fn lua(&self) -> Option<&Frame> {
match self {
CallFrame::Lua(f) => Some(f),
CallFrame::Cont(_) => None,
}
}
#[inline]
pub fn lua_mut(&mut self) -> Option<&mut Frame> {
match self {
CallFrame::Lua(f) => Some(f),
CallFrame::Cont(_) => None,
}
}
}
#[derive(Clone, Copy)]
pub struct NativeCont {
pub kind: ContKind,
pub func_slot: u32,
pub nresults: i32,
}
#[derive(Clone, Copy)]
pub enum ContKind {
Pcall,
Xpcall {
handler: Value,
},
Meta(
MetaCont,
),
Pairs,
Close(
CloseCont,
),
}
#[derive(Clone, Copy)]
pub struct CloseCont {
pub from: u32,
pub pending: Option<Value>,
pub after: AfterClose,
}
#[derive(Clone, Copy)]
pub enum AfterClose {
Block,
Return {
abs_a: u32,
nret: u32,
from_native: bool,
},
ResumeUnwind {
func_slot: u32,
err: Value,
},
}
#[derive(Clone, Copy)]
pub struct MetaCont {
pub action: MetaAction,
pub saved_top: u32,
}
#[derive(Clone, Copy)]
pub enum MetaAction {
Store {
dst: u32,
},
Discard,
Compare {
k: bool,
negate: bool,
},
Concat {
dst: u32,
base_a: u32,
},
}
#[derive(Clone, Debug)]
pub struct UpvalDesc {
pub in_stack: bool,
pub index: u8,
pub name: Box<str>,
pub read_only: bool,
}
#[derive(Clone, Debug)]
pub struct LocVar {
pub name: Box<str>,
pub reg: u32,
pub start_pc: u32,
pub end_pc: u32,
}
#[repr(C)]
pub struct Proto {
pub(crate) hdr: GcHeader,
pub code: Box<[Inst]>,
pub consts: Box<[Value]>,
pub protos: Box<[Gc<Proto>]>,
pub upvals: Box<[UpvalDesc]>,
pub num_params: u8,
pub is_vararg: bool,
pub has_vararg_table_pseudo: bool,
pub has_compat_vararg_arg: bool,
pub max_stack: u8,
pub lines: Box<[u32]>,
pub source: Gc<LuaStr>,
pub line_defined: u32,
pub last_line_defined: u32,
pub locvars: Box<[LocVar]>,
pub cache: std::cell::Cell<Option<Gc<LuaClosure>>>,
pub env_upval_idx: u8,
pub jit: std::cell::Cell<JitProtoState>,
pub trace_hot_count: std::cell::Cell<u32>,
pub call_hot_count: std::cell::Cell<u32>,
pub trace_discard_count: std::cell::Cell<u32>,
pub trace_gave_up: std::cell::Cell<bool>,
pub traces: std::cell::RefCell<Vec<std::rc::Rc<crate::jit::trace::CompiledTrace>>>,
}
#[derive(Clone, Copy, Debug)]
pub enum JitProtoState {
Untried,
Failed,
Compiled {
entry: *const u8,
num_args: u8,
returns_one: bool,
arg_float_mask: u8,
arg_table_mask: u8,
ret_is_float: bool,
ret_is_table: bool,
},
}
impl Proto {
pub(crate) fn trace(&self, m: &mut Marker) {
for &k in self.consts.iter() {
m.value(k);
}
for &p in self.protos.iter() {
m.header(p.as_ptr() as *mut GcHeader);
}
m.header(self.source.as_ptr() as *mut GcHeader);
if self.cache.get().is_some() {
m.cached_protos.push(self as *const Proto as *mut Proto);
}
}
}
pub const INLINE_UPVALS_N: usize = 2;
#[repr(C)]
pub struct LuaClosure {
#[allow(dead_code)]
pub(crate) hdr: GcHeader,
pub proto: Gc<Proto>,
pub(crate) upvals_ptr: *mut Gc<Upvalue>,
pub(crate) upvals_len: u32,
pub(crate) inline_storage: [std::mem::MaybeUninit<Gc<Upvalue>>; INLINE_UPVALS_N],
pub(crate) overflow: Box<[Gc<Upvalue>]>,
}
unsafe impl Send for LuaClosure {}
unsafe impl Sync for LuaClosure {}
impl LuaClosure {
#[inline(always)]
pub fn upvals(&self) -> &[Gc<Upvalue>] {
unsafe { std::slice::from_raw_parts(self.upvals_ptr, self.upvals_len as usize) }
}
#[inline(always)]
pub(crate) fn upvals_mut(&mut self) -> &mut [Gc<Upvalue>] {
unsafe { std::slice::from_raw_parts_mut(self.upvals_ptr, self.upvals_len as usize) }
}
pub(crate) fn init_upvals_ptr(&mut self) {
if self.upvals_len as usize <= INLINE_UPVALS_N {
self.upvals_ptr = self.inline_storage.as_mut_ptr() as *mut Gc<Upvalue>;
} else {
self.upvals_ptr = self.overflow.as_mut_ptr();
}
}
pub(crate) fn trace(&self, m: &mut Marker) {
m.header(self.proto.as_ptr() as *mut GcHeader);
for &uv in self.upvals().iter() {
m.header(uv.as_ptr() as *mut GcHeader);
}
}
}
#[repr(C)]
pub struct NativeClosure {
#[allow(dead_code)]
pub(crate) hdr: GcHeader,
pub f: crate::runtime::value::NativeFn,
pub upvals: Box<[Value]>,
pub is_async: bool,
}
impl NativeClosure {
pub(crate) fn trace(&self, m: &mut Marker) {
for &v in self.upvals.iter() {
m.value(v);
}
}
}
#[repr(C)]
pub struct Upvalue {
#[allow(dead_code)]
pub(crate) hdr: GcHeader,
pub(crate) state: UpvalState,
}
#[derive(Clone, Copy)]
pub enum UpvalState {
Open {
slot: u32,
thread: Option<Gc<crate::runtime::coroutine::Coro>>,
},
Closed(
Value,
),
}
impl Upvalue {
pub fn state(&self) -> UpvalState {
self.state
}
pub(crate) fn set_closed(&mut self, v: Value) {
self.state = UpvalState::Closed(v);
}
pub(crate) fn trace(&self, m: &mut Marker) {
match self.state {
UpvalState::Closed(v) => {
m.value(v);
}
UpvalState::Open {
thread: Some(co), ..
} => {
m.header(co.as_ptr() as *mut GcHeader);
}
UpvalState::Open { thread: None, .. } => {}
}
}
}