Skip to content

Commit

Permalink
Opcode dispatch & variable set/get optimization
Browse files Browse the repository at this point in the history
  * Replace SparseChunk with BitArray; minor improvement
  * Inline a bunch of tight-loopedfunctions: +95% improvement in opcode
execution throughput(!)
  * Drop some trace! stuff for a ~5% improvement.
  * "Peek" optimization (as in LambdaMOO) in the valstack for for-range.  +49% throughput improvement(!)
  • Loading branch information
rdaum committed Jan 7, 2024
1 parent ee10888 commit 554e1bd
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
13 changes: 13 additions & 0 deletions crates/kernel/src/vm/activation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,19 @@ impl Activation {
Vec::from(&self.valstack[l - width..])
}

#[inline]
pub fn peek2(&self) -> (Var, Var) {
let l = self.valstack.len();
let (a, b) = (&self.valstack[l - 1], &self.valstack[l - 2]);
(a.clone(), b.clone())
}

#[inline]
pub fn update(&mut self, amt: usize, v: Var) {
let l = self.valstack.len();
self.valstack[l - amt - 1] = v;
}

#[inline]
pub fn jump(&mut self, label_id: Label) {
let label = &self.program.jump_labels[label_id.0 as usize];
Expand Down
12 changes: 12 additions & 0 deletions crates/kernel/src/vm/exec_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,18 @@ impl VMExecState {
self.top().peek(amt)
}

/// Return the top two values on the value stack.
#[inline]
pub(crate) fn peek2(&self) -> (Var, Var) {
self.top().peek2()
}

/// Update at a set offset in the value stack.
#[inline]
pub(crate) fn update(&mut self, amt: usize, v: &Var) {
self.top_mut().update(amt, v.clone())
}

/// Return the top of the value stack.
#[inline]
pub(crate) fn peek_top(&self) -> Var {
Expand Down
19 changes: 12 additions & 7 deletions crates/kernel/src/vm/vm_execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,7 @@ impl VM {
id,
} => {
// Pull the range ends off the stack.
// TODO LambdaMOO had optimization here where it would only peek and update.
// But I had some difficulty getting stack values right, so will do this simpler
// for now and revisit later.
let (to, from) = (&state.pop(), &state.pop());
let (to, from) = state.peek2();

// TODO: LambdaMOO has special handling for MAXINT/MAXOBJ
// Given we're 64-bit this is highly unlikely to ever be a concern for us, but
Expand All @@ -263,30 +260,38 @@ impl VM {
let next_val = match (to.variant(), from.variant()) {
(Variant::Int(to_i), Variant::Int(from_i)) => {
if from_i > to_i {
state.pop();
state.pop();
state.jump(label);

continue;
}
v_int(from_i + 1)
}
(Variant::Obj(to_o), Variant::Obj(from_o)) => {
if from_o.0 > to_o.0 {
state.pop();
state.pop();
state.jump(label);

continue;
}
v_obj(from_o.0 + 1)
}
(_, _) => {
state.pop();
state.pop();
// Make sure we've jumped out of the loop before raising the error,
// because in verbs that aren't `d' we could end up continuing on in
// the loop (with a messed up stack) otherwise.
state.jump(label);

return self.raise_error(state, E_TYPE);
}
};

state.set_env(id, from);
state.push(&next_val);
state.push(to);
state.update(1, &next_val);
state.set_env(id, &from);
}
Op::Pop => {
state.pop();
Expand Down

0 comments on commit 554e1bd

Please sign in to comment.