Skip to content

Commit

Permalink
Use ArrayVec for short argument arrays
Browse files Browse the repository at this point in the history
Profiling shows a significant amount of time in heap managament,
but with 8 arguments or less these all fit comfortably on the stack.
Adding the dep is easier than handrolling.
  • Loading branch information
bkirwi committed Jan 26, 2022
1 parent 240a98a commit 2e99513
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 18 deletions.
1 change: 1 addition & 0 deletions encrusted-heart/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ license = "MIT"
edition = "2021"

[dependencies]
arrayvec = "0.7.2"
base64 = "0.10.1"
num_enum = "0.5.6"
rand = "0.4.2"
Expand Down
5 changes: 3 additions & 2 deletions encrusted-heart/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use arrayvec::ArrayVec;
use num_enum::TryFromPrimitive;
use std::fmt;
use std::hash;
Expand Down Expand Up @@ -132,7 +133,7 @@ pub enum Opcode {
EXT_1029 = 1029,
}

#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub enum Operand {
Small(u8),
Large(u16),
Expand Down Expand Up @@ -164,7 +165,7 @@ pub struct Branch {
pub struct Instruction {
pub addr: usize,
pub opcode: Opcode,
pub operands: Vec<Operand>,
pub operands: ArrayVec<Operand, 8>,
pub store: Option<u8>,
pub branch: Option<Branch>,
pub text: Option<String>,
Expand Down
48 changes: 32 additions & 16 deletions encrusted-heart/src/zmachine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::options::Options;
use crate::quetzal::QuetzalSave;
use crate::traits::{TextStyle, Window, UI};
use crate::zscii::{ZChar, DEFAULT_UNICODE_TABLE};
use arrayvec::ArrayVec;
use std::cmp::Ordering;
use std::convert::{TryFrom, TryInto};

Expand Down Expand Up @@ -1123,7 +1124,7 @@ impl<ZUI: UI> Zmachine<ZUI> {
self.memory.write(0, save.memory.as_slice());
}

fn get_arguments(&mut self, operands: &[Operand]) -> Vec<u16> {
fn get_arguments(&mut self, operands: &[Operand]) -> ArrayVec<u16, 8> {
operands
.iter()
.map(|operand| match *operand {
Expand Down Expand Up @@ -1182,20 +1183,26 @@ impl<ZUI: UI> Zmachine<ZUI> {
let mut read = self.memory.get_reader(addr);
let first = read.byte();

let btm_4 = |num| num & 0b0000_1111;
let btm_5 = |num| num & 0b0001_1111;

let get_opcode = |code: u8, offset: u16| {
fn btm_4(num: u8) -> u8 {
num & 0b0000_1111
}
fn btm_5(num: u8) -> u8 {
num & 0b0001_1111
}
fn get_opcode(code: u8, offset: u16) -> Opcode {
let num = u16::from(code) + offset;
Opcode::try_from(num).expect("Opcode not found!")
};
}
fn array_vec(slice: &[Operand]) -> ArrayVec<Operand, 8> {
slice.into_iter().copied().collect()
}

#[allow(unreachable_patterns)]
let (opcode, operands) = {
use crate::instruction::Operand::*;

fn get_types(bytes: &[u8], read: &mut Reader) -> Vec<Operand> {
let mut acc = Vec::with_capacity(bytes.len() * 4);
fn get_types(bytes: &[u8], read: &mut Reader) -> ArrayVec<Operand, 8> {
let mut acc = ArrayVec::new();
let mut push_bits = |b: u8| match b {
0b00 => acc.push(Large(read.word())),
0b01 => acc.push(Small(read.byte())),
Expand All @@ -1219,24 +1226,33 @@ impl<ZUI: UI> Zmachine<ZUI> {
),
0x00..=0x1f => (
get_opcode(btm_5(first), 0),
vec![Small(read.byte()), Small(read.byte())],
array_vec(&[Small(read.byte()), Small(read.byte())]),
),
0x20..=0x3f => (
get_opcode(btm_5(first), 0),
vec![Small(read.byte()), Variable(read.byte())],
array_vec(&[Small(read.byte()), Variable(read.byte())]),
),
0x40..=0x5f => (
get_opcode(btm_5(first), 0),
vec![Variable(read.byte()), Small(read.byte())],
array_vec(&[Variable(read.byte()), Small(read.byte())]),
),
0x60..=0x7f => (
get_opcode(btm_5(first), 0),
vec![Variable(read.byte()), Variable(read.byte())],
array_vec(&[Variable(read.byte()), Variable(read.byte())]),
),
0x80..=0x8f => (
get_opcode(btm_4(first), 128),
array_vec(&[Large(read.word())]),
),
0x90..=0x9f => (
get_opcode(btm_4(first), 128),
array_vec(&[Small(read.byte())]),
),
0xa0..=0xaf => (
get_opcode(btm_4(first), 128),
array_vec(&[Variable(read.byte())]),
),
0x80..=0x8f => (get_opcode(btm_4(first), 128), vec![Large(read.word())]),
0x90..=0x9f => (get_opcode(btm_4(first), 128), vec![Small(read.byte())]),
0xa0..=0xaf => (get_opcode(btm_4(first), 128), vec![Variable(read.byte())]),
0xb0..=0xbd | 0xbf => (get_opcode(btm_4(first), 176), vec![]), // OP_0
0xb0..=0xbd | 0xbf => (get_opcode(btm_4(first), 176), ArrayVec::new()), // OP_0
0xc0..=0xdf => (
get_opcode(btm_5(first), 0),
get_types(&[read.byte()], &mut read),
Expand Down

0 comments on commit 2e99513

Please # to comment.