From 5567d64c518a24c0b0abe5d12ccd2a0ad5c1287e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 18:19:45 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Encapsulate=20stack=20dupli?= =?UTF-8?q?cation=20to=20eliminate=20redundant=20stack=20checks=20and=20lo?= =?UTF-8?q?okups=20in=20VM=20execution=20loop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement a dedicated `dup()` method on `ValueStack` to perform stack duplication in a single pass, replacing separate `peek()` and `push()` calls in `Opcode::Dup`. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- .jules/bolt.md | 4 ++++ runtime/vm/src/executor.rs | 3 +-- runtime/vm/src/stack.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 3faa4acb..c33a233e 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -70,3 +70,7 @@ ## 2024-05-24 - Web Property Extraction Optimization **Learning:** Extracting properties from the `RuntimeValue` DSL property lists in `stdlib/src/web/renderer.rs` and `stdlib/src/web/db.rs` was inefficient because the code called `.iter().find()` to resolve `text`, `id`, and `name` attributes, which creates unnecessary iterator overhead and closure allocation. **Action:** Replace `.iter().find()` calls with a single-pass `for p in &dsl.properties` loop and `if` statements on the property names, stopping early when found, which significantly reduces execution overhead. + +## 2026-09-30 - ValueStack duplication optimization +**Learning:** In VM execution loop, handling stack duplication (`Opcode::Dup`) via separate `stack.peek()?` and `stack.push()` calls incurs redundant stack bounds checks and error handling overhead. Encapsulating this in a single `stack.dup()` method simplifies the execution path. +**Action:** Always provide dedicated single-pass methods on collection wrappers (such as `ValueStack::dup`) when an operation involves reading and duplicating the top element on the same structure. diff --git a/runtime/vm/src/executor.rs b/runtime/vm/src/executor.rs index ace9bb00..01b63b29 100644 --- a/runtime/vm/src/executor.rs +++ b/runtime/vm/src/executor.rs @@ -149,8 +149,7 @@ impl VM { } Opcode::Dup => { - let val = self.stack.peek()?.clone(); - self.stack.push(val)?; + self.stack.dup()?; } Opcode::Add => { diff --git a/runtime/vm/src/stack.rs b/runtime/vm/src/stack.rs index f064ad7f..51bf7c3f 100644 --- a/runtime/vm/src/stack.rs +++ b/runtime/vm/src/stack.rs @@ -30,6 +30,16 @@ impl ValueStack { self.data.pop().ok_or(VMError::StackUnderflow) } + /// Duplicates the top value on the stack. + pub fn dup(&mut self) -> Result<(), VMError> { + let val = self.data.last().ok_or(VMError::StackUnderflow)?; + if self.data.len() >= self.max_size { + return Err(VMError::StackOverflow); + } + self.data.push(val.clone()); + Ok(()) + } + /// Returns a reference to the top value. pub fn peek(&self) -> Result<&RuntimeValue, VMError> { self.data.last().ok_or(VMError::StackUnderflow) @@ -80,3 +90,23 @@ impl ValueStack { &self.data } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_stack_dup() { + let mut stack = ValueStack::new(2); + assert_eq!(stack.dup(), Err(VMError::StackUnderflow)); + + stack.push(RuntimeValue::Int(42)).unwrap(); + assert_eq!(stack.len(), 1); + + stack.dup().unwrap(); + assert_eq!(stack.len(), 2); + assert_eq!(stack.peek().unwrap(), &RuntimeValue::Int(42)); + + assert_eq!(stack.dup(), Err(VMError::StackOverflow)); + } +}