From 13f025e4487e40efd285d6998d2261eb992b968e Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 18 Feb 2026 16:28:52 +0000 Subject: [PATCH] pr3.4 --- crates/console/prometeu-vm/src/lib.rs | 2 + crates/console/prometeu-vm/src/roots.rs | 37 +++++++++++++++++++ .../prometeu-vm/src/virtual_machine.rs | 34 +++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 crates/console/prometeu-vm/src/roots.rs diff --git a/crates/console/prometeu-vm/src/lib.rs b/crates/console/prometeu-vm/src/lib.rs index 4331ce4a..140b9990 100644 --- a/crates/console/prometeu-vm/src/lib.rs +++ b/crates/console/prometeu-vm/src/lib.rs @@ -5,8 +5,10 @@ mod virtual_machine; pub mod vm_init_error; pub mod object; pub mod heap; +pub mod roots; pub use prometeu_hal::{HostContext, HostReturn, NativeInterface, SyscallId}; pub use virtual_machine::{BudgetReport, LogicalFrameEndingReason, VirtualMachine}; pub use object::{object_flags, ObjectHeader, ObjectKind}; pub use heap::{Heap, StoredObject}; +pub use roots::{RootVisitor, visit_value_for_roots}; diff --git a/crates/console/prometeu-vm/src/roots.rs b/crates/console/prometeu-vm/src/roots.rs new file mode 100644 index 00000000..fd54f2ce --- /dev/null +++ b/crates/console/prometeu-vm/src/roots.rs @@ -0,0 +1,37 @@ +use prometeu_bytecode::{HeapRef, Value}; + +/// Visitor for GC roots. Implementors receive every `HeapRef` discovered +/// during root traversal. No marking/sweeping semantics here. +pub trait RootVisitor { + fn visit_heap_ref(&mut self, r: HeapRef); +} + +/// Helper: if `val` is a `Value::HeapRef`, call the visitor. +pub fn visit_value_for_roots(val: &Value, visitor: &mut V) { + if let Value::HeapRef(r) = val { + visitor.visit_heap_ref(*r); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::VirtualMachine; + + struct CollectVisitor { pub seen: Vec } + impl RootVisitor for CollectVisitor { + fn visit_heap_ref(&mut self, r: HeapRef) { self.seen.push(r); } + } + + #[test] + fn visits_heapref_on_operand_stack() { + let mut vm = VirtualMachine::default(); + // Place a HeapRef on the operand stack + vm.operand_stack.push(Value::HeapRef(HeapRef(123))); + + let mut v = CollectVisitor { seen: vec![] }; + vm.visit_roots(&mut v); + + assert_eq!(v.seen, vec![HeapRef(123)]); + } +} diff --git a/crates/console/prometeu-vm/src/virtual_machine.rs b/crates/console/prometeu-vm/src/virtual_machine.rs index 5e7f00d3..7e47f499 100644 --- a/crates/console/prometeu-vm/src/virtual_machine.rs +++ b/crates/console/prometeu-vm/src/virtual_machine.rs @@ -5,6 +5,7 @@ use crate::{HostContext, NativeInterface}; use prometeu_bytecode::isa::core::CoreOpCode as OpCode; use prometeu_bytecode::ProgramImage; use prometeu_bytecode::Value; +use crate::roots::{RootVisitor, visit_value_for_roots}; use crate::heap::Heap; use prometeu_bytecode::{ TRAP_BAD_RET_SLOTS, TRAP_DIV_ZERO, TRAP_INVALID_FUNC, TRAP_INVALID_SYSCALL, TRAP_OOB, @@ -1030,6 +1031,39 @@ impl VirtualMachine { Err(OpError::Panic(msg)) => Err(LogicalFrameEndingReason::Panic(msg)), } } + + /// Visit all GC roots reachable from the VM state. + /// This includes: + /// - Entire operand stack values + /// - Locals/args in each call frame (derived from `stack_base` and function layout) + /// - Global variables + pub fn visit_roots(&self, visitor: &mut V) { + // 1) Operand stack (all values are roots) + for v in &self.operand_stack { + visit_value_for_roots(v, visitor); + } + + // 2) Call frames: iterate locals/args range for each frame + for frame in &self.call_stack { + if let Some(func_meta) = self.program.functions.get(frame.func_idx) { + let start = frame.stack_base; + let frame_slots = (func_meta.param_slots as usize) + (func_meta.local_slots as usize); + let mut end = start.saturating_add(frame_slots); + // Clamp to current stack height just in case + if end > self.operand_stack.len() { end = self.operand_stack.len(); } + for i in start..end { + if let Some(v) = self.operand_stack.get(i) { + visit_value_for_roots(v, visitor); + } + } + } + } + + // 3) Globals + for g in &self.globals { + visit_value_for_roots(g, visitor); + } + } } #[cfg(test)]