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 binread::BinRead;
use frame::Frame; use frame::Frame;
use machine::Machine; use machine::Machine;
use std::collections::HashMap;
use std::io::Read; use std::io::Read;
use std::num::Wrapping; use std::num::Wrapping;
use Result; use Result;
@@ -17,79 +16,70 @@ pub enum Args {
Constant, Constant,
} }
#[derive(Clone)]
pub enum Operation { pub enum Operation {
Op(&'static str, OpFunc, Vec<Args>), Op(&'static str, OpFunc, Vec<Args>),
Invalid, Invalid,
} }
const JUMP_OFFSET: i32 = 3; const JUMP_OFFSET: i32 = 3;
const INVALID_OP: Operation = Operation::Invalid;
lazy_static! { lazy_static! {
static ref OPS_MAP: HashMap<u8, Operation> = { static ref OPS_MAP: Vec<Operation> = {
let mut m = HashMap::new(); let mut m = vec![Operation::Invalid; 0xFF + 1];
m.insert(0x00, Operation::Op("NOP", nop, vec![])); m[0x00] = Operation::Op("NOP", nop, vec![]);
m.insert(0x10, Operation::Op("BIPUSH", bipush, vec![Args::Byte])); m[0x10] = Operation::Op("BIPUSH", bipush, vec![Args::Byte]);
m.insert(0x13, Operation::Op("LDC_W", ldc_w, vec![Args::Constant])); m[0x13] = Operation::Op("LDC_W", ldc_w, vec![Args::Constant]);
m.insert(0x15, Operation::Op("ILOAD", iload, vec![Args::Var])); m[0x15] = Operation::Op("ILOAD", iload, vec![Args::Var]);
m.insert(0x36, Operation::Op("ISTORE", istore, vec![Args::Var])); m[0x36] = Operation::Op("ISTORE", istore, vec![Args::Var]);
m.insert(0x57, Operation::Op("POP", pop, vec![])); m[0x57] = Operation::Op("POP", pop, vec![]);
m.insert(0x59, Operation::Op("DUP", dup, vec![])); m[0x59] = Operation::Op("DUP", dup, vec![]);
m.insert(0x5F, Operation::Op("SWAP", swap, vec![])); m[0x5F] = Operation::Op("SWAP", swap, vec![]);
m.insert(0x60, Operation::Op("IADD", iadd, vec![])); m[0x60] = Operation::Op("IADD", iadd, vec![]);
m.insert(0x64, Operation::Op("ISUB", isub, vec![])); m[0x64] = Operation::Op("ISUB", isub, vec![]);
m.insert(0x7E, Operation::Op("IAND", iand, vec![])); m[0x7E] = Operation::Op("IAND", iand, vec![]);
m.insert(0xB0, Operation::Op("IOR", ior, vec![])); m[0xB0] = Operation::Op("IOR", ior, vec![]);
m.insert( m[0x84] = Operation::Op("IINC", iinc, vec![Args::Var, Args::Byte]);
0x84, m[0x99] = Operation::Op("IFEQ", ifeq, vec![Args::Label]);
Operation::Op("IINC", iinc, vec![Args::Var, Args::Byte]), m[0x9b] = Operation::Op("IFLT", iflt, vec![Args::Label]);
); m[0x9F] = Operation::Op("IF_ICMPEQ", if_icmpeq, vec![Args::Label]);
m.insert(0x99, Operation::Op("IFEQ", ifeq, vec![Args::Label])); m[0xA7] = Operation::Op("GOTO", goto, vec![Args::Label]);
m.insert(0x9b, Operation::Op("IFLT", iflt, vec![Args::Label])); m[0xAC] = Operation::Op("IRETURN", ireturn, vec![]);
m.insert( m[0xB6] = Operation::Op("INVOKEVIRTUAL", invokevirtual, vec![Args::Constant]);
0x9F, m[0xC4] = Operation::Op("WIDE", wide, vec![]);
Operation::Op("IF_ICMPEQ", if_icmpeq, vec![Args::Label]), m[0xFC] = Operation::Op("IN", _in, vec![]);
); m[0xFD] = Operation::Op("OUT", out, vec![]);
m.insert(0xA7, Operation::Op("GOTO", goto, vec![Args::Label])); m[0xFE] = Operation::Op("ERR", err, vec![]);
m.insert(0xAC, Operation::Op("IRETURN", ireturn, vec![])); m[0xFF] = Operation::Op("HALT", halt, 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![]));
#[cfg(feature = "extra:sleep")] #[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")] #[cfg(feature = "bonus:network")]
m.insert(0xE1, Operation::Op("NETBIND", netbind, vec![])); {
#[cfg(feature = "bonus:network")] m[0xE1] = Operation::Op("NETBIND", netbind, vec![]);
m.insert(0xE2, Operation::Op("NETCONNECT", netconnect, vec![])); m[0xE2] = Operation::Op("NETCONNECT", netconnect, vec![]);
#[cfg(feature = "bonus:network")] m[0xE3] = Operation::Op("NETIN", netin, vec![]);
m.insert(0xE3, Operation::Op("NETIN", netin, vec![])); m[0xE4] = Operation::Op("NETOUT", netout, vec![]);
#[cfg(feature = "bonus:network")] m[0xE5] = Operation::Op("NETCLOSE", netclose, vec![]);
m.insert(0xE4, Operation::Op("NETOUT", netout, vec![])); }
#[cfg(feature = "bonus:network")]
m.insert(0xE5, Operation::Op("NETCLOSE", netclose, vec![]));
#[cfg(feature = "bonus:heap")] #[cfg(feature = "bonus:heap")]
m.insert(0xD1, Operation::Op("NEWARRAY", newarray, vec![])); {
#[cfg(feature = "bonus:heap")] m[0xD1] = Operation::Op("NEWARRAY", newarray, vec![]);
m.insert(0xD2, Operation::Op("IALOAD", iaload, vec![])); m[0xD2] = Operation::Op("IALOAD", iaload, vec![]);
#[cfg(feature = "bonus:heap")] m[0xD3] = Operation::Op("IASTORE", iastore, vec![]);
m.insert(0xD3, Operation::Op("IASTORE", iastore, vec![])); }
m m
}; };
} }
pub fn num_to_op(op: u8) -> &'static Operation { 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<()> { fn nop(_: &mut Machine) -> Result<()> {