refactor: Vm 状态分组、dispatch 拆分为分发表、IC 辅助函数独立成模块

This commit is contained in:
爱特每羊队
2026-06-25 19:22:16 +08:00
parent 2c8f85d5a9
commit bb3f1cf0e9
16 changed files with 835 additions and 563 deletions
+72 -54
View File
@@ -6,6 +6,7 @@ use oxide_bytecode::module::Constant;
use crate::bindings;
use crate::vm::Vm;
use crate::vm_state::{GcState, IterState, ProfilingState, SymbolState};
use oxide_kernel::kernel::{KernelConfig, KernelCore, KernelSession};
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::mem::{Epoch, P};
@@ -25,17 +26,9 @@ impl Vm {
immutables_cache: Vec::new(),
active_immutables: std::ptr::slice_from_raw_parts(std::ptr::null(), 0),
frames: smallvec::SmallVec::new(),
for_in_iters: Vec::new(),
kernel_core: core,
session,
session_string_ptrs: Vec::new(),
epoch: Epoch::new(),
session_epoch: bumpalo::Bump::new(),
session_gc: crate::session_gc::SessionGc::new(),
forwarding: std::collections::HashMap::with_hasher(rustc_hash::FxBuildHasher),
epoch_object_ptrs: Vec::new(),
session_object_ptrs: Vec::new(),
session_bytes_allocated: 0,
object_prototype: obj_proto,
math_rng_state: 0,
sub_modules: Arc::new(Vec::new()),
@@ -46,18 +39,34 @@ impl Vm {
exception_value: None,
pending_exception: None,
pending_error_kind: None,
symbol_counter: 0,
symbol_descriptions: Vec::new(),
symbol_registry: std::collections::HashMap::new(),
for_of_iters: Vec::new(),
last_for_of_result: JsValue::undefined(),
root_reg_limit: 0,
active_reg_limit: 0,
native_call_depth: 0,
accessor_frame_target_reg: None,
ic_hits: std::cell::Cell::new(0),
ic_misses: std::cell::Cell::new(0),
instruction_count: 0,
gc_state: GcState {
session_epoch: bumpalo::Bump::new(),
session_gc: crate::session_gc::SessionGc::new(),
epoch_object_ptrs: Vec::new(),
session_object_ptrs: Vec::new(),
session_string_ptrs: Vec::new(),
session_bytes_allocated: 0,
forwarding: std::collections::HashMap::with_hasher(rustc_hash::FxBuildHasher),
},
symbols: SymbolState {
symbol_counter: 0,
symbol_descriptions: Vec::new(),
symbol_registry: std::collections::HashMap::new(),
},
iters: IterState {
for_in_iters: Vec::new(),
for_of_iters: Vec::new(),
last_for_of_result: JsValue::undefined(),
},
profiling: ProfilingState {
ic_hits: std::cell::Cell::new(0),
ic_misses: std::cell::Cell::new(0),
instruction_count: 0,
},
}
}
@@ -72,17 +81,9 @@ impl Vm {
immutables_cache: Vec::new(),
active_immutables: std::ptr::slice_from_raw_parts(std::ptr::null(), 0),
frames: smallvec::SmallVec::new(),
for_in_iters: Vec::new(),
kernel_core: core,
session,
session_string_ptrs: Vec::new(),
epoch: Epoch::new(),
session_epoch: bumpalo::Bump::new(),
session_gc: crate::session_gc::SessionGc::new(),
forwarding: std::collections::HashMap::with_hasher(rustc_hash::FxBuildHasher),
epoch_object_ptrs: Vec::new(),
session_object_ptrs: Vec::new(),
session_bytes_allocated: 0,
object_prototype: obj_proto,
math_rng_state: 0,
sub_modules: Arc::new(Vec::new()),
@@ -93,18 +94,34 @@ impl Vm {
exception_value: None,
pending_exception: None,
pending_error_kind: None,
symbol_counter: 0,
symbol_descriptions: Vec::new(),
symbol_registry: std::collections::HashMap::new(),
for_of_iters: Vec::new(),
last_for_of_result: JsValue::undefined(),
root_reg_limit: 0,
active_reg_limit: 0,
native_call_depth: 0,
accessor_frame_target_reg: None,
ic_hits: std::cell::Cell::new(0),
ic_misses: std::cell::Cell::new(0),
instruction_count: 0,
gc_state: GcState {
session_epoch: bumpalo::Bump::new(),
session_gc: crate::session_gc::SessionGc::new(),
epoch_object_ptrs: Vec::new(),
session_object_ptrs: Vec::new(),
session_string_ptrs: Vec::new(),
session_bytes_allocated: 0,
forwarding: std::collections::HashMap::with_hasher(rustc_hash::FxBuildHasher),
},
symbols: SymbolState {
symbol_counter: 0,
symbol_descriptions: Vec::new(),
symbol_registry: std::collections::HashMap::new(),
},
iters: IterState {
for_in_iters: Vec::new(),
for_of_iters: Vec::new(),
last_for_of_result: JsValue::undefined(),
},
profiling: ProfilingState {
ic_hits: std::cell::Cell::new(0),
ic_misses: std::cell::Cell::new(0),
instruction_count: 0,
},
}
}
@@ -138,27 +155,28 @@ impl Vm {
self.active_immutables = std::ptr::slice_from_raw_parts(std::ptr::null(), 0);
self.free_epoch_object_heap_data();
self.epoch.reset();
self.epoch_object_ptrs.clear();
self.session_epoch.reset();
self.session_object_ptrs.clear();
self.session_bytes_allocated = 0;
self.session_gc = crate::session_gc::SessionGc::new();
self.gc_state.epoch_object_ptrs.clear();
self.gc_state.session_epoch.reset();
self.gc_state.session_object_ptrs.clear();
self.gc_state.session_bytes_allocated = 0;
self.gc_state.session_gc = crate::session_gc::SessionGc::new();
self.free_session_string_heap_data();
self.symbol_counter = 0;
self.symbol_descriptions.clear();
self.symbol_registry.clear();
self.symbols.symbol_counter = 0;
self.symbols.symbol_descriptions.clear();
self.symbols.symbol_registry.clear();
self.root_reg_limit = 0;
self.active_reg_limit = 0;
}
fn free_epoch_object_heap_data(&mut self) {
let mut freed = 0u64;
for ptr in self.epoch_object_ptrs.drain(..) {
for ptr in self.gc_state.epoch_object_ptrs.drain(..) {
freed += crate::session_gc::SessionGc::drop_object_heap_data(ptr, false);
}
if freed > 0 {
self.session_gc.total_bytes_freed = self.session_gc.total_bytes_freed.saturating_add(freed);
self.session_gc.last_collection_bytes_freed = freed;
self.gc_state.session_gc.total_bytes_freed =
self.gc_state.session_gc.total_bytes_freed.saturating_add(freed);
self.gc_state.session_gc.last_collection_bytes_freed = freed;
}
}
@@ -171,9 +189,9 @@ impl Vm {
self.regs = [JsValue::undefined(); 256];
self.pc = 0;
self.frames.clear();
self.for_in_iters.clear();
self.for_of_iters.clear();
self.last_for_of_result = JsValue::undefined();
self.iters.for_in_iters.clear();
self.iters.for_of_iters.clear();
self.iters.last_for_of_result = JsValue::undefined();
self.saved_bytecode_stack.clear();
self.saved_immutables_stack.clear();
self.save_stack.clear();
@@ -192,15 +210,15 @@ impl Vm {
self.active_immutables = std::ptr::slice_from_raw_parts(std::ptr::null(), 0);
self.free_epoch_object_heap_data();
self.epoch.reset();
self.epoch_object_ptrs.clear();
self.gc_state.epoch_object_ptrs.clear();
self.root_reg_limit = 0;
self.active_reg_limit = 0;
}
pub fn new_string(&mut self, s: &str) -> JsValue {
let ptr = Box::into_raw(Box::new(JsString::new(s.to_string())));
self.session_string_ptrs.push(ptr);
self.session_bytes_allocated += std::mem::size_of::<JsString>() + s.len();
self.gc_state.session_string_ptrs.push(ptr);
self.gc_state.session_bytes_allocated += std::mem::size_of::<JsString>() + s.len();
JsValue::string(ptr)
}
@@ -224,7 +242,7 @@ impl Vm {
/// can reference them. The lighter `reset()` deliberately keeps them alive,
/// mirroring session-object survival across evals.
fn free_session_string_heap_data(&mut self) {
for ptr in self.session_string_ptrs.drain(..) {
for ptr in self.gc_state.session_string_ptrs.drain(..) {
// SAFETY: each ptr came from Box::into_raw(Box::new(JsString)) in new_string
// and is dropped exactly once here.
unsafe {
@@ -260,7 +278,7 @@ impl Vm {
let prototype_obj = self
.epoch
.alloc(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto_ptr)));
self.epoch_object_ptrs.push(prototype_obj);
self.gc_state.epoch_object_ptrs.push(prototype_obj);
let prototype_val = JsValue::from_js_object(prototype_obj);
let constructor_si = self.kernel_core.perm_interner().intern("constructor").0;
@@ -431,7 +449,7 @@ mod tests {
#[test]
fn session_epoch_survives_reset() {
let mut vm = Vm::new();
let session_ptr = vm.session_epoch.alloc(123i32) as *mut i32;
let session_ptr = vm.gc_state.session_epoch.alloc(123i32) as *mut i32;
vm.reset();
@@ -454,9 +472,9 @@ mod tests {
fn session_epoch_reset_is_only_in_full_reset_state_clear() {
let src = include_str!("vm_support.rs");
let production = src.split("#[cfg(test)]").next().expect("production source");
assert_eq!(production.matches("self.session_epoch.reset()").count(), 1);
assert_eq!(production.matches("self.gc_state.session_epoch.reset()").count(), 1);
assert!(production.contains("fn clear_full_reset_state(&mut self)"));
assert!(production.contains("self.session_epoch.reset();"));
assert!(production.contains("self.gc_state.session_epoch.reset();"));
}
#[test]