mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 19:21:11 +08:00
perf: run 签名改 &Arc<CompiledModule>,顶层模块跨 run 共享——collect_flat_modules 顶层改 Arc::clone 消除逐 run 常量池深拷贝,全调用点 Arc 包装迁移
This commit is contained in:
@@ -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}"),
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//! 时替换为全局对象;箭头/严格/method/构造/显式 receiver 均不替换。
|
||||
//! 覆盖普通调用、call/apply/bind、builtin 回调、构造、生成器、async、derived 构造。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -11,7 +13,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))
|
||||
}
|
||||
|
||||
/// 断言表达式结果为 `true`。
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//! 异常路径不回归、嵌套 try/finally、for-of 迭代器关闭、普通循环零开销路径。
|
||||
//! 字符串值在此引擎 Display 为 `{string}`,断言一律用数值编码。
|
||||
|
||||
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}"),
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
//! 覆盖:读未声明抛 ReferenceError;typeof 未声明返回 "undefined";
|
||||
//! sloppy 写后读正常;harness 全局 var 声明安全;内置标识符不误判。
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
/// 求值并取字符串结果内容(字符串值走 lookup_str,非字符串走 Display)。
|
||||
@@ -21,7 +23,7 @@ fn eval_str(source: &str) -> Result<String, 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))?;
|
||||
let result = vm.run(&module)?;
|
||||
let result = vm.run(&Arc::new(module))?;
|
||||
Ok(vm.lookup_str(result).unwrap_or_default())
|
||||
}
|
||||
|
||||
|
||||
@@ -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}"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user