diff --git a/Cargo.lock b/Cargo.lock index f0c0789..2a2575d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "um" version = "0.1.0" +dependencies = [ + "smallvec", +] diff --git a/Cargo.toml b/Cargo.toml index f3b35d4..971bb3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,10 @@ name = "um" version = "0.1.0" edition = "2021" +[dependencies] +smallvec = { version = "1.13.2", optional = true } + [features] default = ["reclaim-memory"] reclaim-memory = [] +smallvec = ["dep:smallvec"] diff --git a/src/main.rs b/src/main.rs index 940c87a..68b20f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,10 @@ +#[cfg(feature = "smallvec")] +use smallvec::SmallVec; +use std::time::Instant; + +#[cfg(feature = "smallvec")] +const SMALLVEC_SIZE: usize = 24; + fn main() { let mut program = Vec::new(); for arg in std::env::args().skip(1) { @@ -114,6 +121,9 @@ fn decode_ops(ops: &[Platter]) -> Vec { pub struct Um { program_counter: Platter, registers: [Platter; 8], + #[cfg(feature = "smallvec")] + memory: Vec>, + #[cfg(not(feature = "smallvec"))] memory: Vec>, #[cfg(feature = "reclaim-memory")] free_blocks: Vec, @@ -127,7 +137,7 @@ impl Um { pub fn new(program: Vec) -> Self { let ops = decode_ops(&program); Self { - memory: vec![program], + memory: vec![program.into()], ops, ..Default::default() } @@ -381,17 +391,17 @@ impl Um { #[cfg(not(feature = "reclaim-memory"))] fn allocate_memory(&mut self, length: Platter) -> Platter { - self.memory.push(vec![0; length as usize]); + self.memory.push(Self::new_block(length as usize)); (self.memory.len() - 1) as Platter } #[cfg(feature = "reclaim-memory")] fn allocate_memory(&mut self, length: Platter) -> Platter { if let Some(index) = self.free_blocks.pop() { - self.memory[index as usize] = vec![0; length as usize]; + self.memory[index as usize] = Self::new_block(length as usize); index as Platter } else { - self.memory.push(vec![0; length as usize]); + self.memory.push(Self::new_block(length as usize)); (self.memory.len() - 1) as Platter } } @@ -401,7 +411,7 @@ impl Um { #[cfg(feature = "reclaim-memory")] { self.free_blocks.push(block); - self.memory[block as usize] = vec![]; + self.memory[block as usize] = Self::new_block(0); } } @@ -412,4 +422,14 @@ impl Um { self.memory[0][self.program_counter as usize], self.program_counter, self.registers ) } + + #[cfg(feature = "smallvec")] + fn new_block(len: usize) -> SmallVec<[Platter; SMALLVEC_SIZE]> { + smallvec::smallvec![0; len] + } + + #[cfg(not(feature = "smallvec"))] + fn new_block(len: usize) -> Vec { + vec![0; len] + } }