Improve cdef loading time by trimming unnecessary ctype caching

This commit is contained in:
lumi 2025-06-28 05:29:19 +10:00
parent e027623d40
commit ccae0046fb
Signed by: luaneko
GPG Key ID: 406809B8763FF07A
3 changed files with 72 additions and 60 deletions

View File

@ -129,7 +129,7 @@ fn cache_local(f: &mut Formatter, list: &[(&str, &str)]) -> fmt::Result {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct Registry { pub struct Registry {
types: HashSet<String>, types: HashSet<String>,
funcs: HashSet<String>, decls: HashSet<String>,
cdef: String, cdef: String,
lua: String, lua: String,
} }
@ -146,16 +146,16 @@ impl Registry {
pub fn include<T: Type>(&mut self) -> &mut Self { pub fn include<T: Type>(&mut self) -> &mut Self {
self.types self.types
.insert(T::name().to_string()) .insert(T::name().to_string())
.then(|| T::build(&mut TypeBuilder::new::<T>(self))); .then(|| T::build(&mut TypeBuilder::new(self)));
self self
} }
pub fn declare<T: Type>(&mut self, name: impl Display) -> &mut Self { pub fn declare<T: Type>(&mut self, name: impl Display) -> &mut Self {
assert!(T::ty() != TypeType::Void, "cannot declare void type"); assert!(T::ty() != TypeType::Void, "cannot declare void type");
self.include::<T>() self.include::<T>()
.funcs .decls
.insert(name.to_string()) .insert(T::extern_cdecl(&name).to_string())
.then(|| writeln!(self.cdef, "{};", T::extern_cdecl(name)).unwrap()); .then(|| writeln!(self.cdef, "{};", T::extern_cdecl(&name)).unwrap());
self self
} }
@ -184,7 +184,7 @@ impl Display for Registry {
cache_local(f, CACHE_LIBS)?; cache_local(f, CACHE_LIBS)?;
cache_local(f, CACHE_LOCALS)?; cache_local(f, CACHE_LOCALS)?;
writeln!(f, "{}", include_str!("./lib.lua"))?; writeln!(f, "{}", include_str!("./lib.lua"))?;
writeln!(f, "__cdef [[\n{}\n]];", self.cdef.trim())?; writeln!(f, "__cdef [[\n{}\n]];", self.cdef.trim_end())?;
write!(f, "{}", self.lua) write!(f, "{}", self.lua)
} }
} }
@ -210,31 +210,23 @@ pub enum TypeType {
#[derive(Debug)] #[derive(Debug)]
pub struct TypeBuilder<'r> { pub struct TypeBuilder<'r> {
registry: &'r mut Registry, reg: &'r mut Registry,
} }
impl<'r> TypeBuilder<'r> { impl<'r> TypeBuilder<'r> {
fn new<T: Type>(registry: &'r mut Registry) -> Self { fn new(reg: &'r mut Registry) -> Self {
let ct = T::name(); Self { reg }
let cdecl = T::cdecl("");
writeln!(registry.lua, r#"__ct.{ct} = __typeof("{cdecl}");"#).unwrap();
Self { registry }
}
pub fn include<T: Type>(&mut self) -> &mut Self {
self.registry.include::<T>();
self
} }
pub fn cdef<T: Cdef>(&mut self) -> &mut Self { pub fn cdef<T: Cdef>(&mut self) -> &mut Self {
let mut b = CdefBuilder::new::<T>(self.registry); let mut b = CdefBuilder::new::<T>(self.reg);
<T as Cdef>::build(&mut b); <T as Cdef>::build(&mut b);
drop(b); drop(b);
self self
} }
pub fn metatype<T: Metatype>(&mut self) -> &mut Self { pub fn metatype<T: Metatype>(&mut self) -> &mut Self {
let mut b = MetatypeBuilder::new::<T>(self.registry); let mut b = MetatypeBuilder::new::<T>(self.reg);
<T as Metatype>::build(&mut b); <T as Metatype>::build(&mut b);
drop(b); drop(b);
self self
@ -251,16 +243,16 @@ pub unsafe trait Cdef: Type {
#[derive(Debug)] #[derive(Debug)]
pub struct CdefBuilder<'r> { pub struct CdefBuilder<'r> {
registry: &'r mut Registry, reg: &'r mut Registry,
cdef: String, cdef: String,
align: usize, align: usize,
opaque: usize, opaque: usize,
} }
impl<'r> CdefBuilder<'r> { impl<'r> CdefBuilder<'r> {
fn new<T: Cdef>(registry: &'r mut Registry) -> Self { fn new<T: Cdef>(reg: &'r mut Registry) -> Self {
Self { Self {
registry, reg,
cdef: format!("{} {{ ", T::cdecl("")), cdef: format!("{} {{ ", T::cdecl("")),
align: mem::align_of::<T>(), align: mem::align_of::<T>(),
opaque: 0, opaque: 0,
@ -269,7 +261,7 @@ impl<'r> CdefBuilder<'r> {
pub fn field<T: Type>(&mut self, name: impl Display) -> &mut Self { pub fn field<T: Type>(&mut self, name: impl Display) -> &mut Self {
assert!(T::ty() != TypeType::Void, "cannot declare void field"); assert!(T::ty() != TypeType::Void, "cannot declare void field");
self.registry.include::<T>(); self.reg.include::<T>();
self.field_raw(T::cdecl(name)) self.field_raw(T::cdecl(name))
} }
@ -303,14 +295,11 @@ impl<'r> CdefBuilder<'r> {
impl<'r> Drop for CdefBuilder<'r> { impl<'r> Drop for CdefBuilder<'r> {
fn drop(&mut self) { fn drop(&mut self) {
let Self { let Self {
registry, reg, cdef, align, ..
cdef,
align,
..
} = self; } = self;
registry.cdef.push_str(cdef); reg.cdef.push_str(cdef);
writeln!(registry.cdef, "}} __attribute__((aligned({align})));").unwrap(); writeln!(reg.cdef, "}} __attribute__((aligned({align})));").unwrap();
} }
} }
@ -321,26 +310,34 @@ pub unsafe trait Metatype {
#[derive(Debug)] #[derive(Debug)]
pub struct MetatypeBuilder<'r> { pub struct MetatypeBuilder<'r> {
registry: &'r mut Registry, reg: &'r mut Registry,
ct: String, ct: String,
cdef: String, cdef: String,
lua: String, lua: String,
lua_includes: Vec<&'static str>, lua_includes: Vec<&'static str>,
has_index: bool,
} }
impl<'r> MetatypeBuilder<'r> { impl<'r> MetatypeBuilder<'r> {
fn new<T: Metatype>(registry: &'r mut Registry) -> Self { fn new<T: Metatype>(reg: &'r mut Registry) -> Self {
// NOTE: this needs to be written first, because recursively included dependency types might
// need it
let ct = T::Target::name();
let cdecl = T::Target::cdecl("");
writeln!(reg.lua, r#"__ct.{ct} = __typeof("{cdecl}");"#).unwrap();
Self { Self {
registry, reg,
ct: T::Target::name().to_string(), ct: T::Target::name().to_string(),
cdef: String::new(), cdef: String::new(),
lua: r#"do local __mt, __idx = {}, {}; __mt.__index = __idx; "#.into(), lua: String::new(),
lua_includes: vec![], lua_includes: vec![],
has_index: false,
} }
} }
pub fn declare<T: Type>(&mut self, name: impl Display) -> &mut Self { pub fn declare<T: Type>(&mut self, name: impl Display) -> &mut Self {
self.registry.declare::<T>(name); self.reg.declare::<T>(name);
self self
} }
@ -357,11 +354,13 @@ impl<'r> MetatypeBuilder<'r> {
write!(self.lua, "__idx.{name} = ").unwrap(); write!(self.lua, "__idx.{name} = ").unwrap();
f(&mut MetatypeFunctionBuilder::new(self)); f(&mut MetatypeFunctionBuilder::new(self));
writeln!(self.lua, ";").unwrap(); writeln!(self.lua, ";").unwrap();
self.has_index = true;
self self
} }
pub fn index_raw(&mut self, name: impl Display, value: impl Display) -> &mut Self { pub fn index_raw(&mut self, name: impl Display, value: impl Display) -> &mut Self {
writeln!(self.lua, "__idx.{name} = {value};").unwrap(); writeln!(self.lua, "__idx.{name} = {value};").unwrap();
self.has_index = true;
self self
} }
@ -385,18 +384,27 @@ impl<'r> MetatypeBuilder<'r> {
impl<'r> Drop for MetatypeBuilder<'r> { impl<'r> Drop for MetatypeBuilder<'r> {
fn drop(&mut self) { fn drop(&mut self) {
let Self { let Self {
registry, reg,
ct, ct,
cdef, cdef,
lua, lua,
lua_includes: lua_postlude, lua_includes,
has_index,
} = self; } = self;
registry.cdef.push_str(cdef); write!(reg.lua, r#"do local __mt = {{}}; "#).unwrap();
registry.lua.push_str(lua);
writeln!(registry.lua, r#"__metatype(__ct.{ct}, __mt); end;"#).unwrap(); if *has_index {
for lua in lua_postlude { write!(reg.lua, r#"local __idx = {{}}; __mt.__index = __idx; "#).unwrap();
writeln!(registry.lua, r#"do {lua} end;"#).unwrap(); }
reg.cdef.push_str(cdef);
reg.lua.push_str(lua.trim_end());
writeln!(reg.lua, r#"__metatype(__ct.{ct}, __mt); end;"#).unwrap();
for lua in lua_includes {
writeln!(reg.lua, "do {}\nend;", lua.trim_end()).unwrap();
} }
} }
} }
@ -471,7 +479,7 @@ impl<'r, 'm> MetatypeFunctionBuilder<'r, 'm> {
); );
let Self { let Self {
metatype: MetatypeBuilder { registry, .. }, metatype: MetatypeBuilder { reg, .. },
lparams, lparams,
cparams, cparams,
cargs, cargs,
@ -480,7 +488,7 @@ impl<'r, 'm> MetatypeFunctionBuilder<'r, 'm> {
.. ..
} = self; } = self;
registry.include::<T::From>(); reg.include::<T::From>();
(!lparams.is_empty()).then(|| lparams.push_str(", ")); (!lparams.is_empty()).then(|| lparams.push_str(", "));
(!cparams.is_empty()).then(|| cparams.push_str(", ")); (!cparams.is_empty()).then(|| cparams.push_str(", "));
@ -552,13 +560,7 @@ impl<'r, 'm> MetatypeFunctionBuilder<'r, 'm> {
pub fn call<T: IntoFfi>(&mut self, func: impl Display) { pub fn call<T: IntoFfi>(&mut self, func: impl Display) {
let Self { let Self {
metatype: metatype: MetatypeBuilder { reg, cdef, lua, .. },
MetatypeBuilder {
registry,
cdef,
lua,
..
},
lparams, lparams,
cparams, cparams,
cargs, cargs,
@ -567,7 +569,7 @@ impl<'r, 'm> MetatypeFunctionBuilder<'r, 'm> {
.. ..
} = self; } = self;
registry.include::<T::Into>(); reg.include::<T::Into>();
write!(lua, "function({lparams}) {prelude}").unwrap(); write!(lua, "function({lparams}) {prelude}").unwrap();
match T::convention() { match T::convention() {
@ -812,7 +814,7 @@ macro_rules! impl_ptr {
} }
fn build(b: &mut TypeBuilder) { fn build(b: &mut TypeBuilder) {
b.include::<T>(); b.reg.include::<T>();
} }
} }
}; };
@ -1009,7 +1011,7 @@ where
} }
fn build(b: &mut TypeBuilder) { fn build(b: &mut TypeBuilder) {
b.include::<T>(); b.reg.include::<T>();
} }
} }
@ -1039,7 +1041,7 @@ where
} }
fn build(b: &mut TypeBuilder) { fn build(b: &mut TypeBuilder) {
b.include::<T>(); b.reg.include::<T>();
} }
} }
@ -1103,8 +1105,8 @@ macro_rules! impl_externcfn {
} }
fn build(b: &mut TypeBuilder) { fn build(b: &mut TypeBuilder) {
$(b.include::<$arg>();)* $(b.reg.include::<$arg>();)*
b.include::<$ret>(); b.reg.include::<$ret>();
} }
} }
}; };

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
__internal::{disp, display, type_id}, __internal::{disp, display, type_id},
Cdef, CdefBuilder, IntoFfi, KEEP_FN, Type, TypeBuilder, TypeType, Cdef, CdefBuilder, IntoFfi, KEEP_FN, Metatype, MetatypeBuilder, Type, TypeBuilder, TypeType,
}; };
use std::{ffi::c_int, fmt::Display}; use std::{ffi::c_int, fmt::Display};
@ -25,7 +25,7 @@ unsafe impl<T: Type + 'static> Type for lua_option<T> {
} }
fn build(b: &mut TypeBuilder) { fn build(b: &mut TypeBuilder) {
b.cdef::<Self>(); b.cdef::<Self>().metatype::<Self>();
} }
} }
@ -36,6 +36,11 @@ unsafe impl<T: Type + 'static> Cdef for lua_option<T> {
} }
} }
unsafe impl<T: Type + 'static> Metatype for lua_option<T> {
type Target = Self;
fn build(_b: &mut MetatypeBuilder) {}
}
unsafe impl<T: IntoFfi<Into: 'static>> IntoFfi for Option<T> { unsafe impl<T: IntoFfi<Into: 'static>> IntoFfi for Option<T> {
type Into = lua_option<T::Into>; type Into = lua_option<T::Into>;

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
__internal::{disp, display, type_id}, __internal::{disp, display, type_id},
Cdef, CdefBuilder, IntoFfi, KEEP_FN, Type, TypeBuilder, TypeType, Cdef, CdefBuilder, IntoFfi, KEEP_FN, Metatype, MetatypeBuilder, Type, TypeBuilder, TypeType,
string::{DROP_BUFFER_FN, lua_buffer}, string::{DROP_BUFFER_FN, lua_buffer},
}; };
use std::{ffi::c_int, fmt::Display}; use std::{ffi::c_int, fmt::Display};
@ -26,7 +26,7 @@ unsafe impl<T: Type + 'static> Type for lua_result<T> {
} }
fn build(b: &mut TypeBuilder) { fn build(b: &mut TypeBuilder) {
b.cdef::<Self>(); b.cdef::<Self>().metatype::<Self>();
} }
} }
@ -39,6 +39,11 @@ unsafe impl<T: Type + 'static> Cdef for lua_result<T> {
} }
} }
unsafe impl<T: Type + 'static> Metatype for lua_result<T> {
type Target = Self;
fn build(_b: &mut MetatypeBuilder) {}
}
unsafe impl<T: IntoFfi<Into: 'static>, E: Display> IntoFfi for Result<T, E> { unsafe impl<T: IntoFfi<Into: 'static>, E: Display> IntoFfi for Result<T, E> {
type Into = lua_result<T::Into>; type Into = lua_result<T::Into>;