Implement register reuse
This commit is contained in:
parent
d4b13f3193
commit
ac880cc16a
@ -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(®) {
|
||||||
|
// 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() {
|
||||||
|
|||||||
32
src/vm.rs
32
src/vm.rs
@ -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(_) => {}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user