Skip to content

Commit 78a60a5

Browse files
committed
Use HashMap entry API to avoid double lookup on cache miss
1 parent 11741f9 commit 78a60a5

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

src/vm.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,16 @@ impl VM {
348348
.ok_or("CallGlobal: expected symbol")?;
349349
let key = SymbolKey(symbol_rc);
350350

351-
let func_value = if let Some(cached) = self.global_cache.get(&key) {
352-
cached
353-
} else {
354-
let v = self.globals.borrow().get(&*key.0).cloned()
355-
.ok_or_else(|| format!("Undefined function: {}", &*key.0))?;
356-
self.global_cache.insert(key.clone(), v);
357-
self.global_cache.get(&key).unwrap()
351+
// Use entry API to avoid double HashMap lookup on cache miss
352+
use std::collections::hash_map::Entry;
353+
let func_value = match self.global_cache.entry(key) {
354+
Entry::Occupied(e) => e.into_mut(),
355+
Entry::Vacant(e) => {
356+
let name = &*e.key().0;
357+
let v = self.globals.borrow().get(name).cloned()
358+
.ok_or_else(|| format!("Undefined function: {}", name))?;
359+
e.insert(v)
360+
}
358361
};
359362

360363
if let Some(cf) = func_value.as_compiled_function() {
@@ -420,13 +423,16 @@ impl VM {
420423
.ok_or("TailCallGlobal: expected symbol")?;
421424
let key = SymbolKey(symbol_rc);
422425

423-
let func_value = if let Some(cached) = self.global_cache.get(&key) {
424-
cached
425-
} else {
426-
let v = self.globals.borrow().get(&*key.0).cloned()
427-
.ok_or_else(|| format!("Undefined function: {}", &*key.0))?;
428-
self.global_cache.insert(key.clone(), v);
429-
self.global_cache.get(&key).unwrap()
426+
// Use entry API to avoid double HashMap lookup on cache miss
427+
use std::collections::hash_map::Entry;
428+
let func_value = match self.global_cache.entry(key) {
429+
Entry::Occupied(e) => e.into_mut(),
430+
Entry::Vacant(e) => {
431+
let name = &*e.key().0;
432+
let v = self.globals.borrow().get(name).cloned()
433+
.ok_or_else(|| format!("Undefined function: {}", name))?;
434+
e.insert(v)
435+
}
430436
};
431437

432438
if let Some(cf) = func_value.as_compiled_function() {
@@ -677,23 +683,23 @@ impl VM {
677683
let dest = instr.a();
678684
let nargs = instr.b();
679685
let items: Vec<Value> = (0..nargs)
680-
.map(|i| self.registers[base + dest as usize + 1 + i as usize].clone())
686+
.map(|i| unsafe { self.registers.get_unchecked(base + dest as usize + 1 + i as usize) }.clone())
681687
.collect();
682-
self.registers[base + dest as usize] = Value::list(items);
688+
unsafe { *self.registers.get_unchecked_mut(base + dest as usize) = Value::list(items) };
683689
}
684690

685691
Op::GET_LIST => {
686692
let dest = instr.a();
687693
let list = instr.b();
688694
let index = instr.c();
689-
let list_val = &self.registers[base + list as usize];
690-
let idx = &self.registers[base + index as usize];
695+
let list_val = unsafe { self.registers.get_unchecked(base + list as usize) };
696+
let idx = unsafe { self.registers.get_unchecked(base + index as usize) };
691697
let result = if let (Some(items), Some(i)) = (list_val.as_list(), idx.as_int()) {
692698
items.get(i as usize).cloned().unwrap_or(Value::nil())
693699
} else {
694700
return Err("GetList expects list and int".to_string());
695701
};
696-
self.registers[base + dest as usize] = result;
702+
unsafe { *self.registers.get_unchecked_mut(base + dest as usize) = result };
697703
}
698704

699705
Op::SET_LIST => {

0 commit comments

Comments
 (0)