mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
perf: run 签名改 &Arc<CompiledModule>,顶层模块跨 run 共享——collect_flat_modules 顶层改 Arc::clone 消除逐 run 常量池深拷贝,全调用点 Arc 包装迁移
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +287,7 @@ pub fn run_mem_dirty_rebuild_leak(kernel: &Arc<KernelCore>) -> ExitCode {
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
if let Err(e) = vm.run(&module) {
|
||||
if let Err(e) = vm.run(&Arc::new(module)) {
|
||||
eprintln!("[dirty_rebuild] round {round} run failed: {e}");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
@@ -581,7 +581,7 @@ pub fn run_mem_kernel_lifetime() -> ExitCode {
|
||||
Err(_) => return ExitCode::FAILURE,
|
||||
};
|
||||
let js_module = match Compiler::new().compile(&program) {
|
||||
Ok(m) => m,
|
||||
Ok(m) => Arc::new(m),
|
||||
Err(e) => {
|
||||
eprintln!("[kernel_lifetime] js phase compile failed: {e}");
|
||||
return ExitCode::FAILURE;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//! 对比顶层执行结果。**不经 `Compiler::compile`**(测试层直调底层函数)。顶层赋值 /
|
||||
//! escaped 槽样例做字节码/IR 级断言,is_top_level 标志直接断言。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_vm::vm::Vm;
|
||||
use oxide_vm::JsValue;
|
||||
@@ -23,7 +25,7 @@ fn run_source(src: &str, precise: bool) -> Result<JsValue, String> {
|
||||
}
|
||||
let module = oxide_ir::lower::lower(&ir).expect("lower failed");
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 结果规约成可断言形态:`(是否 Ok, 字符串化结果或错误消息)`。
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//! 对比顶层执行结果。副作用纯表读错 VM handler 也能被此兜底。
|
||||
//! **不经 `Compiler::compile`**:测试层直调底层函数,不依赖编译器开关。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_vm::vm::Vm;
|
||||
use oxide_vm::JsValue;
|
||||
|
||||
@@ -19,7 +21,7 @@ fn run_source(src: &str, dce: bool) -> Result<JsValue, String> {
|
||||
}
|
||||
let module = oxide_ir::lower::lower(&ir).expect("lower failed");
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 结果规约成可断言形态:`(是否 Ok, 字符串化结果或错误消息)`。
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
//! on={object} vs off=42)。修复:graph.rs/rewrite.rs 对称 collect_own_escaped。
|
||||
//! 槽号 ≥ inherited_reg_start(param_layout.base)时触发,故用高压力变量推高槽号。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
fn run_source(src: &str, regalloc: bool) -> (bool, String) {
|
||||
@@ -33,7 +35,7 @@ fn run_source(src: &str, regalloc: bool) -> (bool, String) {
|
||||
Err(e) => return (false, format!("lower error: {e}")),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(v) => (true, v.to_string()),
|
||||
Err(e) => (false, e),
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
//! 同一 JS 源码走两条管线:parse → emit → dce(保守恒定)→(regalloc on/off)→ lower → run,
|
||||
//! 对比顶层执行结果。**不经 Compiler::compile**(测试层直调底层函数)。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_vm::vm::Vm;
|
||||
use oxide_vm::JsValue;
|
||||
@@ -29,7 +31,7 @@ fn run_source(src: &str, regalloc: bool) -> Result<JsValue, String> {
|
||||
let mut module = module;
|
||||
oxide_compiler::flatten::flatten_submodules(&mut module);
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 结果规约成可断言形态:`(是否 Ok, 字符串化结果或错误消息)`。
|
||||
|
||||
@@ -695,7 +695,7 @@ fn run_test_inner(
|
||||
};
|
||||
|
||||
let mut vm = Vm::with_kernel_core(Arc::clone(kernel));
|
||||
let run_result = vm.run(&module);
|
||||
let run_result = vm.run(&Arc::new(module));
|
||||
let dur = start.elapsed().as_millis() as u64;
|
||||
|
||||
if is_async {
|
||||
|
||||
@@ -9,7 +9,7 @@ fn bench_call(c: &mut Criterion) {
|
||||
let js = "function fib(n) { if (n < 2) return n; return fib(n-1) + fib(n-2); } fib(15);";
|
||||
let alloc = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&alloc, js).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let module = Arc::new(Compiler::new().compile(&program).expect("compile"));
|
||||
|
||||
c.bench_function("call", |b| {
|
||||
b.iter_batched(
|
||||
|
||||
@@ -9,7 +9,7 @@ fn bench_coercion(c: &mut Criterion) {
|
||||
let js = "var x = \"42\"; var y = \"3.14\"; var r = 0; for (var i = 0; i < 5000; i++) { r += (+x) + (+y); } r";
|
||||
let alloc = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&alloc, js).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let module = Arc::new(Compiler::new().compile(&program).expect("compile"));
|
||||
|
||||
c.bench_function("coercion", |b| {
|
||||
b.iter_batched(
|
||||
|
||||
@@ -9,7 +9,7 @@ fn bench_dispatch(c: &mut Criterion) {
|
||||
let js = "var x = 0; for (var i = 0; i < 10000; i++) { x = x + i - i * 2 + (i % 3); } x";
|
||||
let alloc = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&alloc, js).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let module = Arc::new(Compiler::new().compile(&program).expect("compile"));
|
||||
|
||||
c.bench_function("dispatch", |b| {
|
||||
b.iter_batched(
|
||||
|
||||
@@ -11,7 +11,7 @@ fn bench_gc(c: &mut Criterion) {
|
||||
let js = "var g = {}; for (var i = 0; i < 500; i++) { var obj = { x: i, y: i * 2 }; g[i] = obj; } g[\"x\"]";
|
||||
let alloc = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&alloc, js).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let module = Arc::new(Compiler::new().compile(&program).expect("compile"));
|
||||
|
||||
c.bench_function("gc_mark_sweep", |b| {
|
||||
b.iter_batched(
|
||||
|
||||
@@ -9,7 +9,7 @@ fn bench_property(c: &mut Criterion) {
|
||||
let js = "var obj = { a: 1, b: 2, c: 3, d: 4, e: 5 }; var sum = 0; for (var i = 0; i < 10000; i++) { sum += obj.a + obj.b + obj.c + obj.d + obj.e; } sum";
|
||||
let alloc = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&alloc, js).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let module = Arc::new(Compiler::new().compile(&program).expect("compile"));
|
||||
|
||||
c.bench_function("property", |b| {
|
||||
b.iter_batched(
|
||||
|
||||
@@ -959,6 +959,8 @@ mod tests {
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::*;
|
||||
use crate::vm::{CallFrame, FrameContinuation};
|
||||
use oxide_builtins::{array_buffer, data_view, map, set, typed_array};
|
||||
@@ -1612,8 +1614,10 @@ mod tests {
|
||||
#[test]
|
||||
fn closure_cell_survives_object_sweep() {
|
||||
let mut vm = vm_with_threshold(1);
|
||||
vm.run(&compile("var counter = 0; function inc() { return ++counter; } globalThis.inc = inc; 0"))
|
||||
.expect("run1");
|
||||
vm.run(&Arc::new(compile(
|
||||
"var counter = 0; function inc() { return ++counter; } globalThis.inc = inc; 0",
|
||||
)))
|
||||
.expect("run1");
|
||||
assert!(!vm.gc_state.session_cell_ptrs.borrow().is_empty(), "run1 应分配 upvalue cell");
|
||||
|
||||
// reset 触发对象 sweep:存活对象搬到新 arena,旧 arena 释放。
|
||||
@@ -1636,10 +1640,10 @@ mod tests {
|
||||
#[test]
|
||||
fn private_brand_cell_survives_object_sweep() {
|
||||
let mut vm = vm_with_threshold(1);
|
||||
vm.run(&compile(
|
||||
vm.run(&Arc::new(compile(
|
||||
"class C { #x = 0; set(v){ this.#x = v; } get(){ return this.#x; } } \
|
||||
globalThis.c = new C(); globalThis.c.set(4); 0",
|
||||
))
|
||||
)))
|
||||
.expect("run1");
|
||||
|
||||
vm.reset();
|
||||
@@ -1664,14 +1668,16 @@ mod tests {
|
||||
#[test]
|
||||
fn cells_freed_by_full_reset_and_reallocatable() {
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&compile("var x = 1; function f() { return x; } globalThis.f = f; f()"))
|
||||
vm.run(&Arc::new(compile("var x = 1; function f() { return x; } globalThis.f = f; f()")))
|
||||
.expect("run1");
|
||||
assert!(!vm.gc_state.session_cell_ptrs.borrow().is_empty());
|
||||
|
||||
vm.full_reset();
|
||||
assert!(vm.gc_state.session_cell_ptrs.borrow().is_empty(), "full_reset 应释放全部 cell");
|
||||
|
||||
let result = vm.run(&compile("var y = 2; function g() { return y; } g()")).expect("run2");
|
||||
let result = vm
|
||||
.run(&Arc::new(compile("var y = 2; function g() { return y; } g()")))
|
||||
.expect("run2");
|
||||
assert_eq!(format!("{result}"), "2", "重置后新 cell 应正常分配与读取");
|
||||
}
|
||||
|
||||
|
||||
@@ -446,8 +446,8 @@ pub struct Vm {
|
||||
pub math_rng_state: u64,
|
||||
/// 全局扁平模块表:下标 = 模块 `flat_id`(顶层 0,子模块 flatten 后全局唯一)。
|
||||
/// 闭包 `sub_module_index` 即 flat_id,逃逸闭包也能自足解析。
|
||||
/// 条目为 `Arc<CompiledModule>`,与调用方模块树共享(`run()` 只做 Arc::clone,
|
||||
/// 不再每次深拷贝整棵子树)。
|
||||
/// 条目为 `Arc<CompiledModule>`,与调用方模块树共享:顶层条目即调用方模块
|
||||
/// Arc 同一实例,`run()` 全程只做 Arc::clone,无深拷贝。
|
||||
pub(crate) sub_modules: Arc<Vec<Arc<CompiledModule>>>,
|
||||
/// 帧切换时暂存调用方字节码的 Arc 栈(与 `bytecode` 同共享语义)。
|
||||
pub(crate) saved_bytecode_stack: Vec<Arc<[opcode::Instr]>>,
|
||||
@@ -2801,7 +2801,8 @@ mod tests {
|
||||
is_async: false,
|
||||
});
|
||||
|
||||
vm.run(&module).expect("FOR_OF_CLOSE should tolerate non-object sentinel");
|
||||
vm.run(&Arc::new(module))
|
||||
.expect("FOR_OF_CLOSE should tolerate non-object sentinel");
|
||||
|
||||
assert!(vm.iters.for_of_iters.is_empty());
|
||||
}
|
||||
@@ -2854,7 +2855,9 @@ mod tests {
|
||||
..CompiledModule::new()
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
let err = vm.run(&module).expect_err("unimplemented opcode should fail explicitly");
|
||||
let err = vm
|
||||
.run(&Arc::new(module))
|
||||
.expect_err("unimplemented opcode should fail explicitly");
|
||||
assert_eq!(err, "opcode PROFILE_SHAPE not yet implemented");
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@ use oxide_types::value::JsValue;
|
||||
|
||||
/// 按 `flat_id` 下标收集整棵子模块树为平表,供 `run()` 装载。
|
||||
///
|
||||
/// 子模块节点以 `Arc` 与调用方模块树共享:只做 Arc::clone(O(1) 引用计数),
|
||||
/// 不再深拷贝 constants/upvalue_captures 等。顶层模块本身以浅拷贝包 Arc——
|
||||
/// 其自有 constants 仍逐 run 复制,但整棵子树零深拷贝。
|
||||
fn collect_flat_modules(module: &CompiledModule) -> Vec<Arc<CompiledModule>> {
|
||||
/// 顶层与子模块一律 `Arc` 共享:只做 Arc::clone(O(1) 引用计数),run 期
|
||||
/// 零模块拷贝。唯一可写面 = bytecode 缓冲,经 `bytecode_mut` 的 COW 写时
|
||||
/// 复制——dispatch 期平表与 `Vm.bytecode` 双持(refcount ≥ 2),写必落在
|
||||
/// 私有拷贝上,宿主侧共享缓冲永不被写。
|
||||
fn collect_flat_modules(module: &Arc<CompiledModule>) -> Vec<Arc<CompiledModule>> {
|
||||
let mut out: Vec<Option<Arc<CompiledModule>>> = Vec::new();
|
||||
let top = Arc::new(module.clone());
|
||||
let top = Arc::clone(module);
|
||||
place_flat(&top, &mut out);
|
||||
out.into_iter().map(|m| m.expect("flat_id slot must be filled")).collect()
|
||||
}
|
||||
@@ -518,9 +519,10 @@ impl Vm {
|
||||
|
||||
/// 加载并执行一个已编译模块,返回模块顶层执行结果或未捕获异常消息。
|
||||
///
|
||||
/// 内部初始化寄存器/bytecode/immutables 与 builtin 寄存器预绑定,然后进入
|
||||
/// dispatch 主循环;执行完成或异常展开后返回。
|
||||
pub fn run(&mut self, module: &CompiledModule) -> Result<JsValue, String> {
|
||||
/// 模块以 `Arc` 与调用方共享(如 CodeForge 缓存条目):平表装载只做
|
||||
/// Arc::clone,run 期零模块拷贝。内部初始化寄存器/bytecode/immutables 与
|
||||
/// builtin 寄存器预绑定,然后进入 dispatch 主循环;执行完成或异常展开后返回。
|
||||
pub fn run(&mut self, module: &Arc<CompiledModule>) -> Result<JsValue, String> {
|
||||
vm_debug!("run: starting bytecode execution, {} instructions", module.bytecode.len());
|
||||
self.clear_execution_state();
|
||||
// 模板对象缓存按 run 清空:flat_id 每次 run 从 0 重新分配,跨 run 复用会
|
||||
|
||||
@@ -821,7 +821,7 @@ mod tests {
|
||||
let module = oxide_compiler::compiler::Compiler::new()
|
||||
.compile(&program)
|
||||
.expect("compile failed");
|
||||
vm.run(&module).expect("vm run failed")
|
||||
vm.run(&Arc::new(module)).expect("vm run failed")
|
||||
}
|
||||
|
||||
/// 计数往返:两条构造路径(独立核/共享核)的登记与 Drop 注销恰好配对,
|
||||
@@ -981,7 +981,9 @@ mod tests {
|
||||
let module = oxide_compiler::compiler::Compiler::new()
|
||||
.compile(&program)
|
||||
.expect("compile failed");
|
||||
let err = vm.run(&module).expect_err("runaway allocation must hit the alloc cap");
|
||||
let err = vm
|
||||
.run(&Arc::new(module))
|
||||
.expect_err("runaway allocation must hit the alloc cap");
|
||||
assert!(err.contains("memory limit"), "unexpected error: {err}");
|
||||
assert!(!err.contains("step limit"), "cap 应先于步数上限生效: {err}");
|
||||
}
|
||||
@@ -1015,7 +1017,7 @@ mod tests {
|
||||
let module = oxide_compiler::compiler::Compiler::new()
|
||||
.compile(&program)
|
||||
.expect("compile failed");
|
||||
let err = vm.run(&module).expect_err("reentry pump must hit the alloc cap");
|
||||
let err = vm.run(&Arc::new(module)).expect_err("reentry pump must hit the alloc cap");
|
||||
assert!(err.contains("memory limit"), "unexpected error: {err}");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! arguments 对象执行语义测试:实参个数/索引读取、箭头函数词法继承、
|
||||
//! 默认参数引用、方法调用、闭包捕获、显式声明屏蔽、嵌套函数调用帧边界。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
@@ -25,7 +27,7 @@ fn eval_str(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse ok");
|
||||
let module = Compiler::new().compile(&program).expect("compile ok");
|
||||
let mut vm = Vm::new();
|
||||
let val = vm.run(&module).expect("run ok");
|
||||
let val = vm.run(&Arc::new(module)).expect("run ok");
|
||||
if val.is_string() {
|
||||
vm.lookup_str(val).unwrap_or_default()
|
||||
} else {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -14,7 +16,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {}", e),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{}", result),
|
||||
Err(e) => format!("vm error: {}", e),
|
||||
}
|
||||
@@ -31,7 +33,7 @@ fn eval_val(source: &str) -> (Vm, Result<JsValue, String>) {
|
||||
Err(e) => return (Vm::new(), Err(format!("compile error: {}", e))),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module);
|
||||
let result = vm.run(&Arc::new(module));
|
||||
(vm, result)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! async/await 运行时测试:异步函数调用返回 promise、await 恢复、reject 进 catch、
|
||||
//! 多 await 顺序、嵌套 async、微任务执行序。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::promise::promise_settled_value;
|
||||
@@ -18,7 +20,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format_value(&vm, result),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
//! 覆盖:普通块内函数、块内后续调用、提前调用(阶段 1 现状)、与 let 同名冲突、
|
||||
//! 捕获路径、嵌套块作用域隔离、重复声明(Annex B 最后生效)、单语句块体。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -12,7 +14,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_builtins::array::{array_constructor, array_push};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -8,7 +10,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! AsyncDisposableStack 内置对象测试:构造器/原型形状、use 读取顺序与入栈语义、
|
||||
//! disposeAsync 状态机(微任务序/错误链/防重入/reject 而非抛)、move、GC 交叉。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_kernel::kernel::{KernelConfig, KernelCore};
|
||||
use oxide_parser::Allocator;
|
||||
@@ -19,7 +21,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format_value(&vm, result),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
@@ -487,11 +489,11 @@ fn gc_runtime_collection_keeps_entries() {
|
||||
)
|
||||
.expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
vm.run(&module).expect("run1");
|
||||
vm.run(&Arc::new(module)).expect("run1");
|
||||
let allocator = Allocator::default();
|
||||
let program2 = oxide_parser::parse(&allocator, "globalThis.log.length + ''").expect("parse");
|
||||
let module2 = Compiler::new().compile(&program2).expect("compile");
|
||||
let result = vm.run(&module2).expect("run2");
|
||||
let result = vm.run(&Arc::new(module2)).expect("run2");
|
||||
let text = vm.lookup_str(result).unwrap_or_default().to_string();
|
||||
assert_eq!(text, "200");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "低阈值应触发执行期 GC");
|
||||
@@ -512,7 +514,7 @@ fn promote_then_reset_keeps_entries_alive() {
|
||||
)
|
||||
.expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
vm.run(&module).expect("run1");
|
||||
vm.run(&Arc::new(module)).expect("run1");
|
||||
vm.reset();
|
||||
let allocator = Allocator::default();
|
||||
let program2 = oxide_parser::parse(
|
||||
@@ -522,7 +524,7 @@ fn promote_then_reset_keeps_entries_alive() {
|
||||
)
|
||||
.expect("parse");
|
||||
let module2 = Compiler::new().compile(&program2).expect("compile");
|
||||
let result = vm.run(&module2).expect("run2");
|
||||
let result = vm.run(&Arc::new(module2)).expect("run2");
|
||||
let text = vm.lookup_str(result).unwrap_or_default().to_string();
|
||||
assert_eq!(text, "true|false");
|
||||
}
|
||||
@@ -535,7 +537,7 @@ fn drop_accounts_capability_bytes() {
|
||||
let program = oxide_parser::parse(&allocator, "for (var i = 0; i < 500; i++) { new AsyncDisposableStack(); } 0")
|
||||
.expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
vm.run(&module).expect("run");
|
||||
vm.run(&Arc::new(module)).expect("run");
|
||||
let before = vm.session_gc_stats().total_bytes_freed;
|
||||
vm.reset();
|
||||
let after = vm.session_gc_stats().total_bytes_freed;
|
||||
@@ -551,7 +553,7 @@ fn full_reset_rebuilds_async_disposable_stack() {
|
||||
let allocator = Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, "new AsyncDisposableStack().disposeAsync(); 0").expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
vm.run(&module).expect("run1");
|
||||
vm.run(&Arc::new(module)).expect("run1");
|
||||
vm.full_reset();
|
||||
let allocator = Allocator::default();
|
||||
let program2 = oxide_parser::parse(
|
||||
@@ -566,7 +568,7 @@ fn full_reset_rebuilds_async_disposable_stack() {
|
||||
)
|
||||
.expect("parse");
|
||||
let module2 = Compiler::new().compile(&program2).expect("compile");
|
||||
let result = vm.run(&module2).expect("run2");
|
||||
let result = vm.run(&Arc::new(module2)).expect("run2");
|
||||
let text = match promise_settled_value(unsafe { &*result.as_js_object_ptr() }) {
|
||||
Some((true, v)) => vm.lookup_str(v).unwrap_or_default().to_string(),
|
||||
Some((false, v)) => format!("<rejected {}>", vm.lookup_str(v).unwrap_or_default()),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_builtins::boolean::{boolean_constructor, boolean_prototype_to_string, boolean_prototype_value_of};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::object::JsObject;
|
||||
@@ -10,7 +12,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn str_val(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
@@ -5,7 +7,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<oxide_types::value::JsValue, String
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn str_val(vm: &Vm, val: oxide_types::value::JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_kernel::kernel::{KernelConfig, KernelCore};
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -10,7 +12,7 @@ fn eval_in(vm: &mut Vm, source: &str) -> Result<oxide_types::value::JsValue, Str
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 断言 eval 返回字符串值(session 串在 Vm 内解析)。
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_builtins::error;
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::mem::P;
|
||||
@@ -14,7 +16,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?;
|
||||
let mut vm = make_vm();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 在既有 Vm 内编译执行:结果字符串须在同一 Vm 上下文解析(session 串随 Vm 释放)。
|
||||
@@ -22,7 +24,7 @@ fn eval_in(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -482,7 +484,7 @@ fn error_stack_is_string() {
|
||||
let program = oxide_parser::parse(&allocator, "typeof new Error().stack()").unwrap();
|
||||
let module = Compiler::new().compile(&program).unwrap();
|
||||
let mut vm = make_vm();
|
||||
let result = vm.run(&module).unwrap();
|
||||
let result = vm.run(&Arc::new(module)).unwrap();
|
||||
// typeof 结果复用进程级静态串,同 VM 上读取(跨 VM 指针存活由实现保证,不做假设)。
|
||||
let s = vm.lookup_str(result);
|
||||
assert_eq!(s, Some("string".to_string()));
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 数值断言:整数运算保 int,容忍 int/double 两种表示。
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -8,7 +10,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn eval_with_vm(source: &str) -> (Vm, Result<JsValue, String>) {
|
||||
@@ -16,7 +18,7 @@ fn eval_with_vm(source: &str) -> (Vm, Result<JsValue, String>) {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module);
|
||||
let result = vm.run(&Arc::new(module));
|
||||
(vm, result)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -7,7 +9,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_builtins::map::{map_clear, map_constructor as new_map, map_delete, map_get, map_has, map_set, map_size};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
@@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn str_val(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_builtins::set::{set_add, set_clear, set_constructor as new_set, set_delete, set_has, set_size};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
@@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 分配一个原型指向 Set.prototype 的占位对象并写入 reg 0,作为构造器调用的 `this`。
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
@@ -5,7 +7,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<oxide_types::value::JsValue, String
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn str_val(vm: &Vm, val: oxide_types::value::JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! 调用帧窗口按存活上界拷贝的语义测试:验证压帧窗口缩小后调用方存活寄存器、
|
||||
//! this/new.target、spill 区与异常展开在各类调用路径下恢复正确。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::promise::promise_settled_value;
|
||||
@@ -19,7 +21,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format_value(&vm, result),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! 调用实参 spread 执行语义测试:`f(...args)`、`new F(...args)`、`super(...args)`。
|
||||
//! 覆盖静态/混合实参顺序、迭代器协议、IteratorClose、native 目标、求值顺序。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn assert_num(value: JsValue, expected: f64) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_runtime_api as coercion;
|
||||
@@ -15,7 +17,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
@@ -258,7 +260,7 @@ fn eval_ty(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//! 对象 ToPrimitive 副作用顺序、Symbol 行为与二元 ADD 一致、f64 结合性(右括号不拆)、
|
||||
//! 求值顺序、2 操作数与 3+ 操作数等价性、长链拼接正确性。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -12,7 +14,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {e}"))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//! 声明路径带 b=1 时,checkpoint/寄存器复用残留的陈旧值会误抛 "Assignment to constant variable"。
|
||||
//! 寄存器分配复用寄存器后此问题必现——本测试锁死声明路径恒 b=0 的行为。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -19,7 +21,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn assert_num(value: JsValue, expected: f64) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! eval 脚本 var/函数声明落全局对象的属性语义测试:configurable:true(区别于普通
|
||||
//! 脚本顶层的 false)、可 delete、跨 eval 轮次经全局对象可见。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -10,7 +12,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn eval_many(lines: &[&str]) -> Result<JsValue, String> {
|
||||
@@ -30,7 +32,7 @@ fn eval_str(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
vm.lookup_str(result).unwrap_or_else(|| format!("{result}"))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -7,7 +9,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 数值断言:整数运算保 int,容忍 int/double 两种表示。
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//! 忽略路径(IteratorClose 的 return() 抛错被丢弃)不得把值残留进槽,unwind 进入
|
||||
//! finally/catch 接住异常后槽作废,否则后续 take 会误取残留值污染拒绝原因。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::promise::promise_settled_value;
|
||||
@@ -19,7 +21,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format_value(&vm, result),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! 函数 length/name 属性集成测试:普通字节码函数、箭头函数、bind 包装器、
|
||||
//! getter/setter 前缀。每个用例独立编译执行,断言顶层表达式结果。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_bytecode::module::CompiledModule;
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
@@ -10,11 +12,11 @@ use oxide_vm::vm::Vm;
|
||||
fn eval(source: &str) -> JsValue {
|
||||
let allocator = Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse failed");
|
||||
let module = Compiler::new().compile(&program).expect("compile failed");
|
||||
let module = Arc::new(Compiler::new().compile(&program).expect("compile failed"));
|
||||
run(&module)
|
||||
}
|
||||
|
||||
fn run(module: &CompiledModule) -> JsValue {
|
||||
fn run(module: &Arc<CompiledModule>) -> JsValue {
|
||||
let mut vm = Vm::new();
|
||||
vm.run(module).expect("vm run failed")
|
||||
}
|
||||
@@ -22,7 +24,7 @@ fn run(module: &CompiledModule) -> JsValue {
|
||||
fn eval_str(source: &str) -> String {
|
||||
let allocator = Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse failed");
|
||||
let module = Compiler::new().compile(&program).expect("compile failed");
|
||||
let module = Arc::new(Compiler::new().compile(&program).expect("compile failed"));
|
||||
let mut vm = Vm::new();
|
||||
let v = vm.run(&module).expect("vm run failed");
|
||||
// 字符串结果须在同一 VM 上读:perm 串指向 VM 私有内核,VM drop 后指针悬垂。
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 数值断言:整数运算保 int,容忍 int/double 两种表示。
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_kernel::kernel::{KernelConfig, KernelCore};
|
||||
use oxide_parser::Allocator;
|
||||
@@ -21,7 +23,7 @@ fn vm_with_threshold(bytes: usize) -> Vm {
|
||||
fn long_string_loop_triggers_runtime_gc_and_bounds_session() {
|
||||
let mut vm = vm_with_threshold(4096);
|
||||
let module = compile("var s; for (var i = 0; i < 500000; i++) { s = 'str' + i; } s.length");
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
|
||||
assert_eq!(format!("{}", result), "9");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC");
|
||||
@@ -38,10 +40,10 @@ fn long_string_loop_triggers_runtime_gc_and_bounds_session() {
|
||||
fn session_string_survives_across_runs_with_runtime_gc() {
|
||||
let mut vm = vm_with_threshold(4096);
|
||||
let first = compile("globalThis.kept = 'he' + 'llo'; 0");
|
||||
vm.run(&first).expect("run1");
|
||||
vm.run(&Arc::new(first)).expect("run1");
|
||||
|
||||
let second = compile("var s; for (var i = 0; i < 500000; i++) { s = 'y' + i; } globalThis.kept");
|
||||
let result = vm.run(&second).expect("run2");
|
||||
let result = vm.run(&Arc::new(second)).expect("run2");
|
||||
let text = vm.lookup_str(result).expect("kept 应为字符串").to_string();
|
||||
|
||||
assert_eq!(text, "hello");
|
||||
@@ -53,11 +55,11 @@ fn session_string_survives_across_runs_with_runtime_gc() {
|
||||
fn reset_preserves_session_strings_after_runtime_gc() {
|
||||
let mut vm = vm_with_threshold(4096);
|
||||
let first = compile("globalThis.kept = 'x' + 'y'; 0");
|
||||
vm.run(&first).expect("run1");
|
||||
vm.run(&Arc::new(first)).expect("run1");
|
||||
vm.reset();
|
||||
|
||||
let second = compile("globalThis.kept");
|
||||
let result = vm.run(&second).expect("run2");
|
||||
let result = vm.run(&Arc::new(second)).expect("run2");
|
||||
let text = vm.lookup_str(result).expect("kept 应为字符串").to_string();
|
||||
assert_eq!(text, "xy");
|
||||
}
|
||||
@@ -69,12 +71,12 @@ fn strings_only_then_reset_keeps_global_subtree_strings() {
|
||||
let mut vm = vm_with_threshold(4096);
|
||||
let first =
|
||||
compile("globalThis.kept = { s: 'he' + 'llo' }; var t; for (var i = 0; i < 500000; i++) { t = 'x' + i; } 0");
|
||||
vm.run(&first).expect("run1");
|
||||
vm.run(&Arc::new(first)).expect("run1");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "run1 应触发执行期字符串 GC");
|
||||
vm.reset();
|
||||
|
||||
let second = compile("globalThis.kept.s");
|
||||
let result = vm.run(&second).expect("run2");
|
||||
let result = vm.run(&Arc::new(second)).expect("run2");
|
||||
let text = vm.lookup_str(result).expect("kept.s 应为字符串").to_string();
|
||||
assert_eq!(text, "hello");
|
||||
}
|
||||
@@ -89,7 +91,7 @@ fn regexp_exec_strings_survive_runtime_gc() {
|
||||
"var text = 'a'.repeat(500) + 'b'.repeat(500); var m = /(a+)(b+)/.exec(text); \
|
||||
m[0] + '|' + m[1] + '|' + m[2]",
|
||||
);
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let text = vm.lookup_str(result).expect("exec 结果应为字符串").to_string();
|
||||
let expected = format!("{}|{}|{}", "a".repeat(500) + &"b".repeat(500), "a".repeat(500), "b".repeat(500));
|
||||
assert_eq!(text, expected);
|
||||
@@ -105,7 +107,7 @@ fn temporal_zoned_date_time_strings_survive_runtime_gc() {
|
||||
"var g = {}; for (var i = 0; i < 20; i++) { g['k' + i] = 'v'.repeat(64); } \
|
||||
var z = new Temporal.ZonedDateTime(0n, 'UTC'); z.timeZoneId + '|' + z.calendarId",
|
||||
);
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let text = vm.lookup_str(result).expect("ZDT 槽应为字符串").to_string();
|
||||
assert_eq!(text, "UTC|iso8601");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC");
|
||||
@@ -120,7 +122,7 @@ fn replace_replacer_args_survive_runtime_gc() {
|
||||
"var g = {}; for (var i = 0; i < 20; i++) { g['k' + i] = 'v'.repeat(64); } \
|
||||
'a-b-c'.replace(/(a)-(b)-(c)/g, function(m, p1, p2, p3, pos, s) { return p1 + p2 + p3; })",
|
||||
);
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let text = vm.lookup_str(result).expect("replace 结果应为字符串").to_string();
|
||||
assert_eq!(text, "abc");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC");
|
||||
@@ -141,7 +143,7 @@ fn map_callback_caller_reg_strings_survive_nested_dispatch() {
|
||||
return held; } \
|
||||
var out = middle('mid' + 'str'); out",
|
||||
);
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let text = vm.lookup_str(result).expect("held 应为字符串").to_string();
|
||||
assert_eq!(text, "midstr");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC");
|
||||
@@ -159,7 +161,7 @@ fn replace_replacer_caller_reg_strings_survive_nested_dispatch() {
|
||||
return held + '|' + out; } \
|
||||
var out = middle('repl' + 'acer'); out",
|
||||
);
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let text = vm.lookup_str(result).expect("结果应为字符串").to_string();
|
||||
assert_eq!(text, "replacer|a[-]b[-]c");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC");
|
||||
@@ -178,7 +180,7 @@ fn generator_next_loop_caller_reg_strings_survive_nested_dispatch() {
|
||||
return held + '|' + acc; } \
|
||||
var out = middle('gen' + 'str'); out",
|
||||
);
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let text = vm.lookup_str(result).expect("结果应为字符串").to_string();
|
||||
assert_eq!(text, "genstr|10");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC");
|
||||
@@ -198,7 +200,7 @@ fn nested_inline_callbacks_caller_reg_strings_survive_runtime_gc() {
|
||||
return held + '|' + r.join(','); } \
|
||||
var out = middle('nest' + 'ed'); out",
|
||||
);
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let text = vm.lookup_str(result).expect("结果应为字符串").to_string();
|
||||
assert_eq!(text, "nested|31,32");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC");
|
||||
@@ -210,14 +212,14 @@ fn nested_inline_callbacks_caller_reg_strings_survive_runtime_gc() {
|
||||
fn full_reset_clears_session_after_runtime_gc() {
|
||||
let mut vm = vm_with_threshold(4096);
|
||||
let first = compile("var s; for (var i = 0; i < 200000; i++) { s = 'a' + i; } s.length");
|
||||
vm.run(&first).expect("run1");
|
||||
vm.run(&Arc::new(first)).expect("run1");
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "run1 应触发执行期字符串 GC");
|
||||
|
||||
vm.full_reset();
|
||||
|
||||
assert_eq!(vm.session_bytes_allocated(), 0, "full_reset 后 session 字节应为 0");
|
||||
let second = compile("'ok' + '!'");
|
||||
let result = vm.run(&second).expect("run2");
|
||||
let result = vm.run(&Arc::new(second)).expect("run2");
|
||||
let text = vm.lookup_str(result).expect("拼接结果应为字符串").to_string();
|
||||
assert_eq!(text, "ok!");
|
||||
}
|
||||
@@ -233,13 +235,13 @@ fn reset_sweep_preserves_global_function_object() {
|
||||
for (var i = 0; i < 2000; i++) { var t = 'p' + i + 'q' + i; } \
|
||||
typeof globalThis.fn === 'function'",
|
||||
);
|
||||
let result = vm.run(&first).expect("run1");
|
||||
let result = vm.run(&Arc::new(first)).expect("run1");
|
||||
assert!(result.is_bool() && result.as_bool());
|
||||
assert!(vm.session_gc_stats().total_collections > 0, "低阈值应触发执行期收集");
|
||||
vm.reset();
|
||||
|
||||
let second = compile("typeof globalThis.fn === 'function'");
|
||||
let result = vm.run(&second).expect("run2");
|
||||
let result = vm.run(&Arc::new(second)).expect("run2");
|
||||
assert!(result.is_bool() && result.as_bool());
|
||||
}
|
||||
|
||||
@@ -249,13 +251,13 @@ fn reset_sweep_preserves_global_function_object() {
|
||||
fn closure_cells_freed_by_full_reset_without_double_free() {
|
||||
let mut vm = vm_with_threshold(1);
|
||||
let first = compile("var x = 1; function f() { return x; } globalThis.f = f; f()");
|
||||
let result = vm.run(&first).expect("run1");
|
||||
let result = vm.run(&Arc::new(first)).expect("run1");
|
||||
assert_eq!(format!("{}", result), "1");
|
||||
|
||||
vm.full_reset();
|
||||
|
||||
let second = compile("'ok' + '!'");
|
||||
let result = vm.run(&second).expect("run2");
|
||||
let result = vm.run(&Arc::new(second)).expect("run2");
|
||||
let text = vm.lookup_str(result).expect("拼接结果应为字符串").to_string();
|
||||
assert_eq!(text, "ok!");
|
||||
}
|
||||
@@ -274,12 +276,12 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() {
|
||||
globalThis.dead = function() { return a + b + c; }; \
|
||||
globalThis.live = function() { return a + b + c; }; globalThis.live()",
|
||||
);
|
||||
let result = vm.run(&first).expect("run1");
|
||||
let result = vm.run(&Arc::new(first)).expect("run1");
|
||||
assert_eq!(format!("{}", result), "6");
|
||||
|
||||
// run2:撤销死闭包的根引用(不可达)。
|
||||
let second = compile("globalThis.dead = undefined; 0");
|
||||
vm.run(&second).expect("run2");
|
||||
vm.run(&Arc::new(second)).expect("run2");
|
||||
|
||||
// 完整收集:死闭包走死分支(释放 upvalue 列表),存活闭包走存活分支
|
||||
// (克隆与原件共享 Box,不在死分支释放)。
|
||||
@@ -289,7 +291,7 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() {
|
||||
// 跨 run 存活核(只读属性;跨 run 调用受 sub_module_index 缺口限制):
|
||||
// sweep 后存活闭包克隆仍挂在 global 上。
|
||||
let third = compile("typeof globalThis.live === 'function'");
|
||||
let result = vm.run(&third).expect("run3");
|
||||
let result = vm.run(&Arc::new(third)).expect("run3");
|
||||
assert!(result.is_bool() && result.as_bool());
|
||||
|
||||
// 收尾统一 upvalue 释放与死分支不双放(字段已置空、死对象已出表)。
|
||||
@@ -300,7 +302,7 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() {
|
||||
"var x = 10; var y = 20; var z = 30; \
|
||||
globalThis.f = function() { return x + y + z; }; globalThis.f()",
|
||||
);
|
||||
let result = vm.run(&fourth).expect("run4");
|
||||
let result = vm.run(&Arc::new(fourth)).expect("run4");
|
||||
assert_eq!(format!("{}", result), "60");
|
||||
|
||||
// 字节账目 A/B 差分样本:两条同构 arrow 仅 upvalue 数不同(3 vs 0),
|
||||
@@ -310,8 +312,9 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() {
|
||||
// 死分支不释放 upvalue 列表(泄漏)时差分为 0,本断言转红。
|
||||
let collect_freed = |src: &str| -> u64 {
|
||||
let mut v = vm_with_threshold(4096);
|
||||
v.run(&compile(src)).expect("run create");
|
||||
v.run(&compile("globalThis.arrow = undefined; 0")).expect("run unroot");
|
||||
v.run(&Arc::new(compile(src))).expect("run create");
|
||||
v.run(&Arc::new(compile("globalThis.arrow = undefined; 0")))
|
||||
.expect("run unroot");
|
||||
v.collect_session_gc();
|
||||
let stats = v.session_gc_stats();
|
||||
assert!(stats.last_collection_objects_dead >= 1, "arrow 闭包应经 sweep 死分支");
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
//! sweep 变体与闭包捕获变体见 `vm_support.rs` 内部测试(需 crate 内 `resume_generator`
|
||||
//! 在模块表未重建时恢复执行,integration 层无法触达)。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -18,9 +20,9 @@ fn compile(source: &str) -> oxide_bytecode::module::CompiledModule {
|
||||
#[test]
|
||||
fn generator_promoted_to_global_survives_full_reset_cleanly() {
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&compile(
|
||||
vm.run(&Arc::new(compile(
|
||||
"function* g(){ yield 1; yield 2; } globalThis.it = g(); globalThis.it.next(); 0",
|
||||
))
|
||||
)))
|
||||
.expect("run1");
|
||||
assert!(vm.session_object_count() > 0, "生成器挂 global 应被 promote 进 session");
|
||||
|
||||
@@ -29,12 +31,12 @@ fn generator_promoted_to_global_survives_full_reset_cleanly() {
|
||||
vm.full_reset();
|
||||
assert_eq!(vm.session_object_count(), 0, "full_reset 应清空 session 对象");
|
||||
|
||||
let result = vm.run(&compile("typeof it")).expect("run2");
|
||||
let result = vm.run(&Arc::new(compile("typeof it"))).expect("run2");
|
||||
let text = vm.lookup_str(result).expect("typeof 应返回字符串").to_string();
|
||||
assert_eq!(text, "undefined");
|
||||
// 新会话可正常创建并推进生成器。
|
||||
let ok = vm
|
||||
.run(&compile("function* h(){ yield 9; } var it2 = h(); it2.next().value"))
|
||||
.run(&Arc::new(compile("function* h(){ yield 9; } var it2 = h(); it2.next().value")))
|
||||
.expect("run3");
|
||||
assert_eq!(format!("{ok}"), "9");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! `yield*` 委托语法运行时测试:委托数组/字符串/生成器,next/return/throw 转发,
|
||||
//! 委托完成值传递与空委托场景。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -16,7 +18,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => {
|
||||
if result.is_string() {
|
||||
vm.lookup_str(result).unwrap_or_default()
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
//! 保持(writable 不翻位、NaN/Infinity 不被抹成 undefined)、var 初始化声明的值
|
||||
//! 落槽、枚举面不泄漏、任务只读拦截与 strict TypeError、eval 路径、for-in 枚举面。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -17,13 +19,13 @@ fn compile(source: &str) -> oxide_bytecode::module::CompiledModule {
|
||||
|
||||
fn run_truthy(source: &str) {
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&compile(source)).expect("run");
|
||||
let result = vm.run(&Arc::new(compile(source))).expect("run");
|
||||
assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}");
|
||||
}
|
||||
|
||||
fn run_string(source: &str) -> String {
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&compile(source)).expect("run");
|
||||
let result = vm.run(&Arc::new(compile(source))).expect("run");
|
||||
if result.is_undefined() {
|
||||
return "undefined".to_string();
|
||||
}
|
||||
@@ -33,7 +35,7 @@ fn run_string(source: &str) -> String {
|
||||
/// 求值并返回完成值字符串;运行期异常返回错误文本(供 TypeError 断言)。
|
||||
fn eval(source: &str) -> String {
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&compile(source)) {
|
||||
match vm.run(&Arc::new(compile(source))) {
|
||||
Ok(result) => vm.lookup_str(result).unwrap_or_default(),
|
||||
Err(e) => e,
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//! enumerable=false(不泄漏进 Object.keys(globalThis) / for-in),
|
||||
//! 全局 NaN/undefined/Infinity 三常量不可写不可枚举可配置。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -11,7 +13,7 @@ fn eval_truthy(source: &str) {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! 脚本顶层 var/function 声明落 globalThis 的运行时行为测试。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -9,7 +11,7 @@ fn eval_truthy(source: &str) {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}");
|
||||
}
|
||||
|
||||
@@ -18,7 +20,7 @@ fn eval_string(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
vm.lookup_str(result).unwrap_or_default()
|
||||
}
|
||||
|
||||
@@ -31,9 +33,9 @@ fn compile(source: &str) -> oxide_bytecode::module::CompiledModule {
|
||||
/// 两阶段执行:phase1 → `reset()`(轻量重置,epoch 清空、session 保留)→ phase2。
|
||||
fn eval_two_phases(phase1: &str, phase2: &str) -> bool {
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&compile(phase1)).expect("run1");
|
||||
vm.run(&Arc::new(compile(phase1))).expect("run1");
|
||||
vm.reset();
|
||||
let result = vm.run(&compile(phase2)).expect("run2");
|
||||
let result = vm.run(&Arc::new(compile(phase2))).expect("run2");
|
||||
result.is_bool() && result.as_bool()
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
//! 覆盖的 shape 只产生"每 shape 一次"的学习 miss,超出槽容量的轮换则
|
||||
//! 每次访问都 miss(FIFO 逐访问滚动)。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -15,7 +17,7 @@ fn run_once(source: &str) -> (String, u64, u64) {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let r = vm.run(&module).expect("run").to_string();
|
||||
let r = vm.run(&Arc::new(module)).expect("run").to_string();
|
||||
(r, vm.ic_hit_count(), vm.ic_miss_count())
|
||||
}
|
||||
|
||||
@@ -143,7 +145,7 @@ fn rerun_clears_polymorphic_slots() {
|
||||
.expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module).expect("run1");
|
||||
vm.run(&Arc::new(module)).expect("run1");
|
||||
let learned = vm.ic_miss_count();
|
||||
// run() 每次冷启动,此处直接验证 rerun 的可重入性:清除后仍能正常执行。
|
||||
assert_eq!(format!("{}", vm.rerun().expect("rerun")), "1500");
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
//! 覆盖脚本顶层、函数体(全局对象经 session 解析,不依赖 this)、解构目标、
|
||||
//! 更新式/逻辑赋值、for-in/for-of 左侧与不可扩展全局对象分支。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -12,7 +14,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn eval_many(lines: &[&str]) -> Result<JsValue, String> {
|
||||
@@ -32,7 +34,7 @@ fn eval_str(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
vm.lookup_str(result).unwrap_or_else(|| format!("{result}"))
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
//! 覆盖生成器体内 C 侧路径触发的构造后 throw 与取值两种形态;帧边界
|
||||
//! (字节码 GET_PROP 压 getter 帧)形态与循环失控形态(test262 族)另行回测。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
@@ -16,7 +18,7 @@ fn eval_str(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
vm.lookup_str(result).unwrap_or_else(|| format!("{result}"))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn string_value(vm: &Vm, val: JsValue) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! 循环每迭代绑定(CreatePerIterationEnvironment):for/for-of/for-in 的 let/const
|
||||
//! 闭包捕获各自迭代快照。对应 PLAN 06-01(正确性报告 P1/P2)。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -10,7 +12,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
//!
|
||||
//! 计数断言基于单次 run 内 miss/hit 对比(run() 每次冷启动,IC 学习不跨 run)。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -16,7 +18,7 @@ fn run_once(source: &str) -> (String, u64, u64) {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
// 字符串结果经 lookup_str 提取内容(JsValue Display 只打印 {string})。
|
||||
let r = vm.lookup_str(result).unwrap_or_else(|| format!("{result}"));
|
||||
(r, vm.ic_hit_count(), vm.ic_miss_count())
|
||||
@@ -184,7 +186,7 @@ fn member_write_counts_in_ic_hit_rate() {
|
||||
.expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
let r = vm.lookup_str(result).unwrap_or_else(|| format!("{result}"));
|
||||
assert_eq!(r, "1000");
|
||||
// 循环写侧 1000 命中 + 末尾 IC_GET 1 miss → 命中率 ~0.999(写侧计入后趋近真实)。
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn assert_bool(value: JsValue, expected: bool) {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
//! 变化,说明双计机制已变——须对照 tests/stress/mem_object_graph.js 的基线
|
||||
//! (benchmark_baseline.json)复核后再更新本锚。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -32,7 +34,7 @@ fn run_module(source: &str) -> Vm {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
assert_eq!(result.to_string(), "9", "root.left.id(2) + root.right.right.id(7)");
|
||||
vm
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -13,7 +15,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
@@ -26,7 +28,7 @@ fn object_create_and_read() {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse failed");
|
||||
let module = Compiler::new().compile(&program).expect("compile failed");
|
||||
let mut vm = Vm::new();
|
||||
let obj = vm.run(&module).expect("vm run failed");
|
||||
let obj = vm.run(&Arc::new(module)).expect("vm run failed");
|
||||
assert!(obj.is_object());
|
||||
let obj_ref = unsafe { &*obj.as_js_object_ptr() };
|
||||
assert_eq!(obj_ref.prop_count(), 1, "object should have 1 property");
|
||||
@@ -273,7 +275,7 @@ fn eval_string(source: &str) -> String {
|
||||
let mut vm = Vm::new();
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse failed");
|
||||
let module = Compiler::new().compile(&program).expect("compile failed");
|
||||
let result = vm.run(&module).expect("vm run failed");
|
||||
let result = vm.run(&Arc::new(module)).expect("vm run failed");
|
||||
vm.lookup_str(result).unwrap_or_default()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::promise::promise_settled_value;
|
||||
@@ -7,7 +9,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
/// 顶层表达式返回 Promise 时,run() 末尾 drain 已执行微任务,读其结算值。
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//! (密集数组 int 键界内直读写)与各回退场景(越界、hole、accessor、非数组、
|
||||
//! 非对象 receiver)与 ordinary 属性路径行为一致。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -11,7 +13,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn eval_many(lines: &[&str]) -> Result<JsValue, String> {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
// 返回保活的 Vm:结果可能含对象指针(数组/描述符),读取前必须保持 Vm 存活,
|
||||
@@ -17,7 +19,7 @@ fn eval_keep_vm(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok((vm, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
macro_rules! assert_bool {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
//! 绑定(var/let/参数)与其他可写内置(Math)不受影响。逻辑赋值额外钉住
|
||||
//! 短路时序:短路未通过不发生 put(strict 不抛),通过才在写点拦截。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -14,7 +16,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn eval_many(lines: &[&str]) -> Result<JsValue, String> {
|
||||
@@ -34,7 +36,7 @@ fn eval_str(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
vm.lookup_str(result).unwrap_or_else(|| format!("{result}"))
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
@@ -33,7 +33,7 @@ fn eval_with_kernel(source: &str, kernel: Arc<KernelCore>) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::with_kernel_core(kernel);
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{result}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
@@ -52,12 +52,12 @@ fn regression_rerun_clears_ic_cache() {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
assert_eq!(format!("{}", vm.run(&module).unwrap()), "1");
|
||||
assert_eq!(format!("{}", vm.run(&Arc::new(module)).unwrap()), "1");
|
||||
|
||||
let source2 = "var o = {a: 2}; o.a";
|
||||
let program2 = oxide_parser::parse(&allocator, source2).expect("parse");
|
||||
let module2 = Compiler::new().compile(&program2).expect("compile");
|
||||
vm.run(&module2).unwrap();
|
||||
vm.run(&Arc::new(module2)).unwrap();
|
||||
assert_eq!(
|
||||
format!("{}", vm.rerun().unwrap()),
|
||||
"2",
|
||||
@@ -188,7 +188,7 @@ fn eval_shallow(source: &str, depth: usize) -> String {
|
||||
let mut cfg = KernelConfig::minimal();
|
||||
cfg.max_call_depth = depth;
|
||||
let mut vm = Vm::with_kernel_core(KernelCore::new(cfg));
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(val) => {
|
||||
if val.is_string() {
|
||||
vm.lookup_str(val).unwrap_or_default().to_string()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! rest 参数集成测试:实参收集、length 交互、与 spread/箭头/闭包组合。
|
||||
//! 每个用例独立编译执行,断言顶层表达式结果。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -11,7 +13,7 @@ fn eval(source: &str) -> JsValue {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse failed");
|
||||
let module = Compiler::new().compile(&program).expect("compile failed");
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module).expect("vm run failed")
|
||||
vm.run(&Arc::new(module)).expect("vm run failed")
|
||||
}
|
||||
|
||||
fn eval_int(source: &str) -> i32 {
|
||||
@@ -30,7 +32,7 @@ fn eval_str(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse failed");
|
||||
let module = Compiler::new().compile(&program).expect("compile failed");
|
||||
let mut vm = Vm::new();
|
||||
let v = vm.run(&module).expect("vm run failed");
|
||||
let v = vm.run(&Arc::new(module)).expect("vm run failed");
|
||||
// 字符串结果须在同一 VM 上读:perm 串指向 VM 私有内核,VM drop 后指针悬垂。
|
||||
if v.is_string() {
|
||||
vm.lookup_str(v).unwrap_or_default()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -7,7 +9,7 @@ fn run_source(vm: &mut Vm, source: &str) -> JsValue {
|
||||
let allocator = Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse failed");
|
||||
let module = Compiler::new().compile(&program).expect("compile failed");
|
||||
vm.run(&module).expect("vm run failed")
|
||||
vm.run(&Arc::new(module)).expect("vm run failed")
|
||||
}
|
||||
|
||||
fn global_prop(vm: &Vm, name: &str) -> JsValue {
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
//! 覆盖脚本顶层(`top_level_strict`)、函数级(帧 `strict`)与内联内置回调
|
||||
//! (forEach 等,`inline_strict` + 帧基线)三种执行上下文。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -12,7 +14,7 @@ fn eval(source: &str) -> Result<JsValue, String> {
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn eval_many(lines: &[&str]) -> Result<JsValue, String> {
|
||||
@@ -32,7 +34,7 @@ fn eval_str(source: &str) -> String {
|
||||
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
||||
let module = Compiler::new().compile(&program).expect("compile");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run");
|
||||
let result = vm.run(&Arc::new(module)).expect("run");
|
||||
vm.lookup_str(result).unwrap_or_else(|| format!("{result}"))
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
//!
|
||||
//! 手工 IR 是唯一可达路径——RegAlloc 未接入,真实 JS 编译产物不会含三指令。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_bytecode::module::Constant;
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_ir::inst::Inst;
|
||||
@@ -15,7 +17,7 @@ fn run_ir(ir: IRFunction) -> String {
|
||||
// 手工 IR 不经 Compiler::compile,需手动扁平化子模块(create_closure 相对索引)。
|
||||
oxide_compiler::flatten::flatten_submodules(&mut module);
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(v) => format!("{v}"),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//! for-of/属性键/模板/JSON/展开)的惰性扁平化正确性、数字/对象叶子混合、CONCAT_N
|
||||
//! 产物作 rope 叶子、低 GC 阈值下跨执行期字符串回收的存活与 mark 传播。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_kernel::kernel::{KernelConfig, KernelCore};
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -13,7 +15,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {e}"))?;
|
||||
vm.run(&module)
|
||||
vm.run(&Arc::new(module))
|
||||
}
|
||||
|
||||
fn eval_str(source: &str) -> String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_bytecode::module::Constant;
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
@@ -19,7 +21,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {}", e),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => format!("{}", result),
|
||||
Err(e) => format!("vm error: {}", e),
|
||||
}
|
||||
@@ -36,7 +38,7 @@ fn eval_val(source: &str) -> (Vm, Result<JsValue, String>) {
|
||||
Err(e) => return (Vm::new(), Err(format!("compile error: {}", e))),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module);
|
||||
let result = vm.run(&Arc::new(module));
|
||||
(vm, result)
|
||||
}
|
||||
|
||||
@@ -134,7 +136,7 @@ fn template_expression_reads_physical_register_above_127() {
|
||||
|
||||
let module = oxide_ir::lower::lower(&ir).expect("lower template IR");
|
||||
let mut vm = Vm::new();
|
||||
let result = vm.run(&module).expect("run template IR");
|
||||
let result = vm.run(&Arc::new(module)).expect("run template IR");
|
||||
assert_eq!(to_str(&vm, result), "value");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! test262 宿主对象 `$262` 的最小绑定验证:对象存在、`global` 指向当前 realm
|
||||
//! 全局、evalScript 可执行、未实现方法抛能力缺失错误。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_vm::vm::Vm;
|
||||
@@ -17,7 +19,7 @@ fn eval(source: &str) -> String {
|
||||
Err(e) => return format!("compile error: {e}"),
|
||||
};
|
||||
let mut vm = Vm::new();
|
||||
match vm.run(&module) {
|
||||
match vm.run(&Arc::new(module)) {
|
||||
Ok(result) => vm.lookup_str(result).unwrap_or_else(|| format!("{result}")),
|
||||
Err(e) => format!("vm error: {e}"),
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user