Refactor global variable access in VM and optimizer

Replaces `Rc<RefCell<Vec<Value>>>` with a new `GlobalStore` struct for
accessing global variables. This provides a more structured way to
manage global values and allows for future optimizations like sharing
immutable RTL portions across environments. The `GlobalStore` also
includes an `rtl_len` field to distinguish between RTL and user global
slots, enabling debug-time checks for writes to immutable RTL slots.
This commit is contained in:
2026-03-27 23:40:42 +01:00
parent 893d9936ed
commit 0e8cd0832f
6 changed files with 89 additions and 44 deletions
+40 -15
View File
@@ -82,9 +82,43 @@ impl VMObserver for TracingObserver {
}
}
/// Unified view of the global value space for VM and optimizer access.
///
/// Wraps a flat `Vec<Value>` containing both RTL slots `[0..rtl_len)` and user
/// slots `[rtl_len..)`. The `rtl_len` boundary is informational — it enables
/// a debug-mode write guard and prepares for future RTL sharing.
///
/// True RTL/user splitting (sharing the immutable RTL portion across environments)
/// is a planned future optimization once the stream-bootstrap timing is resolved.
#[derive(Clone)]
pub struct GlobalStore {
values: Rc<RefCell<Vec<Value>>>,
/// Index boundary between frozen RTL slots and mutable user slots.
pub rtl_len: usize,
}
impl GlobalStore {
pub fn new(values: Rc<RefCell<Vec<Value>>>, rtl_len: usize) -> Self {
Self { values, rtl_len }
}
pub fn get(&self, idx: usize) -> Option<Value> {
self.values.borrow().get(idx).cloned()
}
fn set(&self, idx: usize, value: Value) {
debug_assert!(idx >= self.rtl_len, "Cannot write to immutable RTL slot {}", idx);
let mut v = self.values.borrow_mut();
if idx >= v.len() {
v.resize(idx + 1, Value::Void);
}
v[idx] = value;
}
}
pub struct VM {
stack: Vec<Value>,
globals: Rc<RefCell<Vec<Value>>>,
globals: GlobalStore,
frames: Vec<CallFrame>,
/// Side-channel for tail-call signaling. Set by `eval_internal` when a tail-call
/// is requested; consumed by `resolve_tail_calls` and the inline TCO loop.
@@ -92,7 +126,7 @@ pub struct VM {
}
impl VM {
pub fn new(globals: Rc<RefCell<Vec<Value>>>) -> Self {
pub fn new(globals: GlobalStore) -> Self {
Self {
stack: Vec::new(),
globals,
@@ -883,13 +917,9 @@ impl VM {
}
}
Address::Global(idx) => {
let g_idx = idx.0 as usize;
let globals = self.globals.borrow();
if g_idx < globals.len() {
Ok(globals[g_idx].clone())
} else {
Err(format!("Global access out of bounds {}", idx))
}
self.globals
.get(idx.0 as usize)
.ok_or_else(|| format!("Global access out of bounds {}", idx))
}
Address::Upvalue(idx) => {
let frame = self.frames.last().ok_or("No call frame")?;
@@ -926,12 +956,7 @@ impl VM {
Ok(())
}
Address::Global(idx) => {
let g_idx = idx.0 as usize;
let mut globals = self.globals.borrow_mut();
if g_idx >= globals.len() {
globals.resize(g_idx + 1, Value::Void);
}
globals[g_idx] = value;
self.globals.set(idx.0 as usize, value);
Ok(())
}
Address::Upvalue(idx) => {