Refine chunk poisoning and optimize taking values from registers
This commit is contained in:
parent
87f597624a
commit
d587d87ed7
@ -72,8 +72,14 @@ impl Vm {
|
|||||||
Operation::Move => {
|
Operation::Move => {
|
||||||
let to_register = instruction.a();
|
let to_register = instruction.a();
|
||||||
let from_register = instruction.b();
|
let from_register = instruction.b();
|
||||||
|
let from_register_has_value = self
|
||||||
|
.stack
|
||||||
|
.get(from_register as usize)
|
||||||
|
.is_some_and(|register| !matches!(register, Register::Empty));
|
||||||
|
|
||||||
self.set_pointer(to_register, from_register, position)?;
|
if from_register_has_value {
|
||||||
|
self.set_pointer(to_register, from_register, position)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Operation::Close => {
|
Operation::Close => {
|
||||||
let from_register = instruction.b();
|
let from_register = instruction.b();
|
||||||
@ -434,8 +440,9 @@ impl Vm {
|
|||||||
value: Value,
|
value: Value,
|
||||||
position: Span,
|
position: Span,
|
||||||
) -> Result<(), VmError> {
|
) -> Result<(), VmError> {
|
||||||
let length = self.stack.len();
|
|
||||||
self.last_assigned_register = Some(to_register);
|
self.last_assigned_register = Some(to_register);
|
||||||
|
|
||||||
|
let length = self.stack.len();
|
||||||
let to_register = to_register as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
if length == Self::STACK_LIMIT {
|
if length == Self::STACK_LIMIT {
|
||||||
@ -481,8 +488,9 @@ impl Vm {
|
|||||||
from_register: u8,
|
from_register: u8,
|
||||||
position: Span,
|
position: Span,
|
||||||
) -> Result<(), VmError> {
|
) -> Result<(), VmError> {
|
||||||
let length = self.stack.len();
|
|
||||||
self.last_assigned_register = Some(to_register);
|
self.last_assigned_register = Some(to_register);
|
||||||
|
|
||||||
|
let length = self.stack.len();
|
||||||
let to_register = to_register as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
if length == Self::STACK_LIMIT {
|
if length == Self::STACK_LIMIT {
|
||||||
@ -528,8 +536,9 @@ impl Vm {
|
|||||||
constant_index: u8,
|
constant_index: u8,
|
||||||
position: Span,
|
position: Span,
|
||||||
) -> Result<(), VmError> {
|
) -> Result<(), VmError> {
|
||||||
let length = self.stack.len();
|
|
||||||
self.last_assigned_register = Some(to_register);
|
self.last_assigned_register = Some(to_register);
|
||||||
|
|
||||||
|
let length = self.stack.len();
|
||||||
let to_register = to_register as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
if length == Self::STACK_LIMIT {
|
if length == Self::STACK_LIMIT {
|
||||||
@ -598,26 +607,31 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let register = replace(&mut self.stack[index], Register::Empty);
|
let register = replace(&mut self.stack[index], Register::Empty);
|
||||||
|
let value = match register {
|
||||||
match register {
|
Register::Value(value) => value,
|
||||||
Register::Value(value) => Ok(value),
|
Register::Pointer(register_index) => self.empty_register(register_index, position)?,
|
||||||
Register::Pointer(register_index) => {
|
|
||||||
let value = self.empty_register(register_index, position)?;
|
|
||||||
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
Register::Constant(constant_index) => {
|
Register::Constant(constant_index) => {
|
||||||
let constants = &mut self.chunk.constants_mut();
|
let constant_index = constant_index as usize;
|
||||||
|
|
||||||
constants.push(Value::integer(0));
|
if constant_index >= self.chunk.constants().len() {
|
||||||
|
return Err(VmError::Chunk {
|
||||||
|
error: ChunkError::ConstantIndexOutOfBounds {
|
||||||
|
index: constant_index,
|
||||||
|
},
|
||||||
|
position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let value = constants.swap_remove(constant_index as usize);
|
let constant = &mut self.chunk.constants_mut()[constant_index];
|
||||||
self.chunk.is_poisoned = true;
|
|
||||||
|
|
||||||
Ok(value)
|
replace(constant, Value::integer(0))
|
||||||
}
|
}
|
||||||
Register::Empty => Err(VmError::EmptyRegister { index, position }),
|
Register::Empty => return Err(VmError::EmptyRegister { index, position }),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
self.chunk.is_poisoned = true;
|
||||||
|
|
||||||
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&mut self, position: Span) -> Result<&(Instruction, Span), VmError> {
|
fn read(&mut self, position: Span) -> Result<&(Instruction, Span), VmError> {
|
||||||
|
Loading…
Reference in New Issue
Block a user