mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 统一 reset 与 rerun 的运行态清理
This commit is contained in:
+64
-20
@@ -290,13 +290,24 @@ impl Vm {
|
|||||||
&self.epoch
|
&self.epoch
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
fn clear_execution_state(&mut self) {
|
||||||
self.regs = [JsValue::undefined(); 256];
|
self.regs = [JsValue::undefined(); 256];
|
||||||
self.pc = 0;
|
self.pc = 0;
|
||||||
self.bytecode.clear();
|
|
||||||
self.constants.clear();
|
|
||||||
self.frames.clear();
|
self.frames.clear();
|
||||||
self.for_in_iters.clear();
|
self.for_in_iters.clear();
|
||||||
|
self.for_of_iters.clear();
|
||||||
|
self.saved_bytecode_stack.clear();
|
||||||
|
self.saved_constants_stack.clear();
|
||||||
|
self.try_stack.clear();
|
||||||
|
self.exception_value = None;
|
||||||
|
self.pending_exception = None;
|
||||||
|
self.pending_error_kind = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.clear_execution_state();
|
||||||
|
self.bytecode.clear();
|
||||||
|
self.constants.clear();
|
||||||
self.epoch.reset();
|
self.epoch.reset();
|
||||||
self.interned_strings.clear();
|
self.interned_strings.clear();
|
||||||
self.root_reg_limit = 0;
|
self.root_reg_limit = 0;
|
||||||
@@ -511,15 +522,8 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn rerun(&mut self) -> Result<JsValue, String> {
|
pub fn rerun(&mut self) -> Result<JsValue, String> {
|
||||||
self.pc = 0;
|
self.clear_execution_state();
|
||||||
self.regs = [JsValue::undefined(); 256];
|
|
||||||
self.active_reg_limit = self.root_reg_limit;
|
self.active_reg_limit = self.root_reg_limit;
|
||||||
self.frames.clear();
|
|
||||||
self.for_in_iters.clear();
|
|
||||||
self.try_stack.clear();
|
|
||||||
self.exception_value = None;
|
|
||||||
self.pending_exception = None;
|
|
||||||
self.pending_error_kind = None;
|
|
||||||
self.clear_ic_caches();
|
self.clear_ic_caches();
|
||||||
self.dispatch()
|
self.dispatch()
|
||||||
}
|
}
|
||||||
@@ -542,21 +546,13 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, module: &CompiledModule) -> Result<JsValue, String> {
|
pub fn run(&mut self, module: &CompiledModule) -> Result<JsValue, String> {
|
||||||
|
self.clear_execution_state();
|
||||||
self.constants = self.convert_constants(module);
|
self.constants = self.convert_constants(module);
|
||||||
self.sub_modules = module.sub_modules.clone();
|
self.sub_modules = module.sub_modules.clone();
|
||||||
self.sub_module_constants = vec![Vec::new(); self.sub_modules.len()];
|
self.sub_module_constants = vec![Vec::new(); self.sub_modules.len()];
|
||||||
self.bytecode = module.bytecode.clone();
|
self.bytecode = module.bytecode.clone();
|
||||||
self.pc = 0;
|
|
||||||
self.regs = [JsValue::undefined(); 256];
|
|
||||||
self.root_reg_limit = module.n_registers.max(1);
|
self.root_reg_limit = module.n_registers.max(1);
|
||||||
self.active_reg_limit = self.root_reg_limit;
|
self.active_reg_limit = self.root_reg_limit;
|
||||||
self.frames.clear();
|
|
||||||
self.saved_bytecode_stack.clear();
|
|
||||||
self.saved_constants_stack.clear();
|
|
||||||
self.try_stack.clear();
|
|
||||||
self.exception_value = None;
|
|
||||||
self.pending_exception = None;
|
|
||||||
self.pending_error_kind = None;
|
|
||||||
|
|
||||||
for (name, reg) in &module.builtin_reg_map {
|
for (name, reg) in &module.builtin_reg_map {
|
||||||
let si = self.kernel.string_forge().intern(name.as_str()).0;
|
let si = self.kernel.string_forge().intern(name.as_str()).0;
|
||||||
@@ -1910,3 +1906,51 @@ impl Default for Vm {
|
|||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{opcode, JsValue, TryHandler, Vm};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reset_clears_runtime_state_like_rerun() {
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
vm.regs[1] = JsValue::int(7);
|
||||||
|
vm.pc = 3;
|
||||||
|
vm.frames.push(super::CallFrame {
|
||||||
|
return_addr: 1,
|
||||||
|
function_name: 0,
|
||||||
|
caller_reg_limit: 2,
|
||||||
|
saved_regs: vec![JsValue::undefined()].into_boxed_slice(),
|
||||||
|
saved_this: JsValue::undefined(),
|
||||||
|
saved_new_target: JsValue::undefined(),
|
||||||
|
});
|
||||||
|
vm.for_in_iters.push(std::ptr::dangling_mut::<u8>());
|
||||||
|
vm.for_of_iters.push(std::ptr::dangling_mut::<u8>());
|
||||||
|
vm.saved_bytecode_stack
|
||||||
|
.push(vec![opcode::encode(opcode::OpCode::HALT, 0, 0, 0)]);
|
||||||
|
vm.saved_constants_stack.push(vec![JsValue::int(1)]);
|
||||||
|
vm.try_stack.push(TryHandler {
|
||||||
|
catch_pc: Some(1),
|
||||||
|
finally_pc: None,
|
||||||
|
frame_depth: 0,
|
||||||
|
});
|
||||||
|
vm.exception_value = Some(JsValue::int(2));
|
||||||
|
vm.pending_exception = Some(JsValue::int(3));
|
||||||
|
vm.pending_error_kind = Some("TypeError");
|
||||||
|
|
||||||
|
vm.reset();
|
||||||
|
|
||||||
|
assert_eq!(vm.pc, 0);
|
||||||
|
assert!(vm.frames.is_empty());
|
||||||
|
assert!(vm.for_in_iters.is_empty());
|
||||||
|
assert!(vm.for_of_iters.is_empty());
|
||||||
|
assert!(vm.saved_bytecode_stack.is_empty());
|
||||||
|
assert!(vm.saved_constants_stack.is_empty());
|
||||||
|
assert!(vm.try_stack.is_empty());
|
||||||
|
assert!(vm.exception_value.is_none());
|
||||||
|
assert!(vm.pending_exception.is_none());
|
||||||
|
assert!(vm.pending_error_kind.is_none());
|
||||||
|
assert!(vm.bytecode.is_empty());
|
||||||
|
assert!(vm.constants.is_empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user