Implement register reuse

This commit is contained in:
Sofia 2026-03-16 17:49:58 +02:00
parent d4b13f3193
commit ac880cc16a
2 changed files with 41 additions and 17 deletions

View File

@ -30,10 +30,18 @@ pub struct Scope {
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct LocalCounter(u16); pub struct LocalCounter(u16, Vec<u16>);
impl LocalCounter { impl LocalCounter {
pub fn next(&mut self) -> u16 { pub fn next(&mut self) -> u16 {
if let Some(reg) = self.1.pop() {
reg
} else {
self.new()
}
}
pub fn new(&mut self) -> u16 {
let temp = self.0; let temp = self.0;
self.0 += 1; self.0 += 1;
temp temp
@ -238,6 +246,18 @@ impl Statement {
} }
} }
for reg in 0..scope.register_counter.0 {
if scope.locals.values().find(|r| **r == reg).is_some() {
// Register is still in use
continue;
}
if scope.register_counter.1.contains(&reg) {
// Register is already in the list of unused registers
continue;
}
scope.register_counter.1.push(reg);
}
instructions instructions
} }
} }
@ -433,10 +453,10 @@ impl Expression {
original_param_regs.extend(registers); original_param_regs.extend(registers);
} }
let function_reg = scope.register_counter.next(); let function_reg = scope.register_counter.new();
let mut param_regs = Vec::new(); let mut param_regs = Vec::new();
for _ in &original_param_regs { for _ in &original_param_regs {
param_regs.push(scope.register_counter.next()); param_regs.push(scope.register_counter.new());
} }
for (i, param_reg) in original_param_regs.iter().enumerate().rev() { for (i, param_reg) in original_param_regs.iter().enumerate().rev() {

View File

@ -104,6 +104,8 @@ pub enum RuntimeError {
InvalidOperands(BinaryOperator, Value, Value), InvalidOperands(BinaryOperator, Value, Value),
#[error("Unable to perform {0:?} operator to {1:?}")] #[error("Unable to perform {0:?} operator to {1:?}")]
InvalidOperand(UnaryOperator, Value), InvalidOperand(UnaryOperator, Value),
#[error("Tried calling a non-function: {0:?}")]
TriedCallingNonFunction(Value),
#[error("{0}")] #[error("{0}")]
Custom(String), Custom(String),
} }
@ -234,7 +236,9 @@ impl Debug for Value {
.field(&LuaNumber::from_bits(*arg0)) .field(&LuaNumber::from_bits(*arg0))
.finish(), .finish(),
Self::RustFunction(arg0) => f.debug_tuple("RustFunction").field(arg0).finish(), Self::RustFunction(arg0) => f.debug_tuple("RustFunction").field(arg0).finish(),
Self::Function(_) => f.debug_tuple("Function").finish(), Self::Function(closure) => f
.debug_tuple(&format!("Function({})", closure.prototype))
.finish(),
Self::Nil => write!(f, "Nil"), Self::Nil => write!(f, "Nil"),
} }
} }
@ -384,22 +388,28 @@ impl ClosureRunner {
); );
} }
Instruction::GetGlobal(reg, global) => { Instruction::GetGlobal(reg, global) => {
if let Some(global) = self let glob = self
.closure .closure
.environment .environment
.borrow() .borrow()
.globals .globals
.get(constants.get(*global as usize).unwrap()) .get(constants.get(*global as usize).unwrap())
{ .cloned();
self.stack if let Some(global) = glob {
.insert(*reg, Rc::new(RefCell::new(global.clone()))); self.set_stack(*reg, global.clone());
} else { } else {
todo!("Global not found: {:?}", constants.get(*global as usize)) todo!("Global not found: {:?}", constants.get(*global as usize))
} }
} }
Instruction::GetUpVal(reg, upvalreg) => { Instruction::GetUpVal(reg, upvalreg) => {
self.stack self.set_stack(
.insert(*reg, self.closure.upvalues.get(upvalreg).unwrap().clone()); *reg,
self.closure
.upvalues
.get(upvalreg)
.map(|v| v.borrow().clone())
.unwrap(),
);
} }
Instruction::SetUpVal(upvalreg, reg) => { Instruction::SetUpVal(upvalreg, reg) => {
*self.closure.upvalues.get(upvalreg).unwrap().borrow_mut() = self *self.closure.upvalues.get(upvalreg).unwrap().borrow_mut() = self
@ -489,13 +499,7 @@ impl ClosureRunner {
} }
self.inner = Some(Box::new(closure.run(params))); self.inner = Some(Box::new(closure.run(params)));
} }
_ => { _ => return Err(RuntimeError::TriedCallingNonFunction(value.clone())),
if *ret_len > 0 {
for i in 0..=(*ret_len - 2) {
self.set_stack(*func_reg + i, Value::Nil);
}
}
}
} }
} }
Instruction::Close(_) => {} Instruction::Close(_) => {}