From 71daed8790eb3e01e2ec0cfb9732cd66a3eaaae9 Mon Sep 17 00:00:00 2001 From: Jur van den Berg Date: Mon, 8 Apr 2019 16:35:07 +0200 Subject: [PATCH] Use a vector instead of a hashmap, 2.5x speedup --- src/ops.rs | 96 ++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/src/ops.rs b/src/ops.rs index ec1a6f5..7ae7a33 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -1,7 +1,6 @@ use binread::BinRead; use frame::Frame; use machine::Machine; -use std::collections::HashMap; use std::io::Read; use std::num::Wrapping; use Result; @@ -17,79 +16,70 @@ pub enum Args { Constant, } +#[derive(Clone)] pub enum Operation { Op(&'static str, OpFunc, Vec), Invalid, } const JUMP_OFFSET: i32 = 3; -const INVALID_OP: Operation = Operation::Invalid; lazy_static! { - static ref OPS_MAP: HashMap = { - let mut m = HashMap::new(); + static ref OPS_MAP: Vec = { + let mut m = vec![Operation::Invalid; 0xFF + 1]; - m.insert(0x00, Operation::Op("NOP", nop, vec![])); - m.insert(0x10, Operation::Op("BIPUSH", bipush, vec![Args::Byte])); - m.insert(0x13, Operation::Op("LDC_W", ldc_w, vec![Args::Constant])); - m.insert(0x15, Operation::Op("ILOAD", iload, vec![Args::Var])); - m.insert(0x36, Operation::Op("ISTORE", istore, vec![Args::Var])); - m.insert(0x57, Operation::Op("POP", pop, vec![])); - m.insert(0x59, Operation::Op("DUP", dup, vec![])); - m.insert(0x5F, Operation::Op("SWAP", swap, vec![])); - m.insert(0x60, Operation::Op("IADD", iadd, vec![])); - m.insert(0x64, Operation::Op("ISUB", isub, vec![])); - m.insert(0x7E, Operation::Op("IAND", iand, vec![])); - m.insert(0xB0, Operation::Op("IOR", ior, vec![])); - m.insert( - 0x84, - Operation::Op("IINC", iinc, vec![Args::Var, Args::Byte]), - ); - m.insert(0x99, Operation::Op("IFEQ", ifeq, vec![Args::Label])); - m.insert(0x9b, Operation::Op("IFLT", iflt, vec![Args::Label])); - m.insert( - 0x9F, - Operation::Op("IF_ICMPEQ", if_icmpeq, vec![Args::Label]), - ); - m.insert(0xA7, Operation::Op("GOTO", goto, vec![Args::Label])); - m.insert(0xAC, Operation::Op("IRETURN", ireturn, vec![])); - m.insert( - 0xB6, - Operation::Op("INVOKEVIRTUAL", invokevirtual, vec![Args::Constant]), - ); - m.insert(0xC4, Operation::Op("WIDE", wide, vec![])); - m.insert(0xFC, Operation::Op("IN", _in, vec![])); - m.insert(0xFD, Operation::Op("OUT", out, vec![])); - m.insert(0xFE, Operation::Op("ERR", err, vec![])); - m.insert(0xFF, Operation::Op("HALT", halt, vec![])); + m[0x00] = Operation::Op("NOP", nop, vec![]); + m[0x10] = Operation::Op("BIPUSH", bipush, vec![Args::Byte]); + m[0x13] = Operation::Op("LDC_W", ldc_w, vec![Args::Constant]); + m[0x15] = Operation::Op("ILOAD", iload, vec![Args::Var]); + m[0x36] = Operation::Op("ISTORE", istore, vec![Args::Var]); + m[0x57] = Operation::Op("POP", pop, vec![]); + m[0x59] = Operation::Op("DUP", dup, vec![]); + m[0x5F] = Operation::Op("SWAP", swap, vec![]); + m[0x60] = Operation::Op("IADD", iadd, vec![]); + m[0x64] = Operation::Op("ISUB", isub, vec![]); + m[0x7E] = Operation::Op("IAND", iand, vec![]); + m[0xB0] = Operation::Op("IOR", ior, vec![]); + m[0x84] = Operation::Op("IINC", iinc, vec![Args::Var, Args::Byte]); + m[0x99] = Operation::Op("IFEQ", ifeq, vec![Args::Label]); + m[0x9b] = Operation::Op("IFLT", iflt, vec![Args::Label]); + m[0x9F] = Operation::Op("IF_ICMPEQ", if_icmpeq, vec![Args::Label]); + m[0xA7] = Operation::Op("GOTO", goto, vec![Args::Label]); + m[0xAC] = Operation::Op("IRETURN", ireturn, vec![]); + m[0xB6] = Operation::Op("INVOKEVIRTUAL", invokevirtual, vec![Args::Constant]); + m[0xC4] = Operation::Op("WIDE", wide, vec![]); + m[0xFC] = Operation::Op("IN", _in, vec![]); + m[0xFD] = Operation::Op("OUT", out, vec![]); + m[0xFE] = Operation::Op("ERR", err, vec![]); + m[0xFF] = Operation::Op("HALT", halt, vec![]); #[cfg(feature = "extra:sleep")] - m.insert(0xF0, Operation::Op("SLP", slp, vec![Args::Byte])); + { + m[0xF0] = Operation::Op("SLP", slp, vec![Args::Byte]); + } #[cfg(feature = "bonus:network")] - m.insert(0xE1, Operation::Op("NETBIND", netbind, vec![])); - #[cfg(feature = "bonus:network")] - m.insert(0xE2, Operation::Op("NETCONNECT", netconnect, vec![])); - #[cfg(feature = "bonus:network")] - m.insert(0xE3, Operation::Op("NETIN", netin, vec![])); - #[cfg(feature = "bonus:network")] - m.insert(0xE4, Operation::Op("NETOUT", netout, vec![])); - #[cfg(feature = "bonus:network")] - m.insert(0xE5, Operation::Op("NETCLOSE", netclose, vec![])); + { + m[0xE1] = Operation::Op("NETBIND", netbind, vec![]); + m[0xE2] = Operation::Op("NETCONNECT", netconnect, vec![]); + m[0xE3] = Operation::Op("NETIN", netin, vec![]); + m[0xE4] = Operation::Op("NETOUT", netout, vec![]); + m[0xE5] = Operation::Op("NETCLOSE", netclose, vec![]); + } #[cfg(feature = "bonus:heap")] - m.insert(0xD1, Operation::Op("NEWARRAY", newarray, vec![])); - #[cfg(feature = "bonus:heap")] - m.insert(0xD2, Operation::Op("IALOAD", iaload, vec![])); - #[cfg(feature = "bonus:heap")] - m.insert(0xD3, Operation::Op("IASTORE", iastore, vec![])); + { + m[0xD1] = Operation::Op("NEWARRAY", newarray, vec![]); + m[0xD2] = Operation::Op("IALOAD", iaload, vec![]); + m[0xD3] = Operation::Op("IASTORE", iastore, vec![]); + } m }; } pub fn num_to_op(op: u8) -> &'static Operation { - OPS_MAP.get(&op).unwrap_or(&INVALID_OP) + &OPS_MAP[op as usize] } fn nop(_: &mut Machine) -> Result<()> {