Skip to content

Commit 77cbbb5

Browse files
committed
perf: skip unused value-stack lanes when entering a function
Entering a function reserved and zero-filled all three value-stack lanes even when the function never touches the 64- or 128-bit lane, which is the common case. Skip a lane whose locals and operand-stack depth are both zero. A single-result return now moves the result down and truncates once, instead of popping, truncating and pushing it back.
1 parent 7160f7f commit 77cbbb5

1 file changed

Lines changed: 18 additions & 8 deletions

File tree

‎crates/tinywasm/src/interpreter/stack/value_stack.rs‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,15 @@ impl<T: Copy + Default> Stack<T> {
135135
self.data.truncate(n);
136136
}
137137

138+
/// Moves the top value down to index `n` and drops everything above it (a function's result
139+
/// replacing its frame).
138140
#[inline(always)]
139141
pub(crate) fn truncate_to_one_tail(&mut self, n: usize) {
140-
debug_assert!(n < self.data.len());
141-
let last = self.pop();
142-
self.data.truncate(n);
143-
self.data.push(last);
142+
let len = self.data.len();
143+
debug_assert!(n < len);
144+
let last = self.data[len.wrapping_sub(1)];
145+
self.data[n] = last;
146+
self.data.truncate(n + 1);
144147
}
145148

146149
/// Enters a function: turns its parameters into the first locals, zeroes the rest, and reserves
@@ -276,10 +279,17 @@ impl ValueStack {
276279
) -> Result<StackBase, Trap> {
277280
let locals_base32 =
278281
self.stack_32.enter_locals(params.c32 as usize, locals.c32 as usize, max_stack.c32 as usize)?;
279-
let locals_base64 =
280-
self.stack_64.enter_locals(params.c64 as usize, locals.c64 as usize, max_stack.c64 as usize)?;
281-
let locals_base128 =
282-
self.stack_128.enter_locals(params.c128 as usize, locals.c128 as usize, max_stack.c128 as usize)?;
282+
// Most functions use only the 32-bit lane; an unused lane needs no reservation.
283+
let locals_base64 = if locals.c64 | max_stack.c64 == 0 {
284+
self.stack_64.len() as u32
285+
} else {
286+
self.stack_64.enter_locals(params.c64 as usize, locals.c64 as usize, max_stack.c64 as usize)?
287+
};
288+
let locals_base128 = if locals.c128 | max_stack.c128 == 0 {
289+
self.stack_128.len() as u32
290+
} else {
291+
self.stack_128.enter_locals(params.c128 as usize, locals.c128 as usize, max_stack.c128 as usize)?
292+
};
283293
Ok(StackBase { s32: locals_base32, s64: locals_base64, s128: locals_base128 })
284294
}
285295

0 commit comments

Comments
 (0)