Use a vector instead of a hashmap, 2.5x speedup

This commit is contained in:
2019-04-08 16:35:07 +02:00
parent 6ed58151ee
commit 71daed8790

View File

@@ -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<Args>),
Invalid,
}
const JUMP_OFFSET: i32 = 3;
const INVALID_OP: Operation = Operation::Invalid;
lazy_static! {
static ref OPS_MAP: HashMap<u8, Operation> = {
let mut m = HashMap::new();
static ref OPS_MAP: Vec<Operation> = {
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<()> {