mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: NEW_OBJECT 走统一分配入口登记 epoch 对象消除属性向量泄漏
This commit is contained in:
@@ -227,9 +227,7 @@ impl Vm {
|
||||
shape_id = self.kernel_core.shape_forge().make_shape(shape_id, si);
|
||||
}
|
||||
}
|
||||
let obj = self
|
||||
.epoch
|
||||
.alloc(JsObject::new_empty(shape_id, JsValue::from_js_object(proto_ptr)));
|
||||
let obj = self.alloc_object(JsObject::new_empty(shape_id, JsValue::from_js_object(proto_ptr)));
|
||||
// 预分配数据槽并同步 generation:批量一次性 +nprops,与逐属性路径的终值一致。
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
for _ in 0..nprops {
|
||||
|
||||
@@ -87,3 +87,48 @@ fn test_full_reset_clears_session_state() {
|
||||
let result = run_source(&mut vm, "globalThis.x");
|
||||
assert!(result.is_undefined());
|
||||
}
|
||||
|
||||
/// NEW_OBJECT 字面量必须登记进 epoch 追踪表:`{}` 写入超内联容量的属性会分配
|
||||
/// hash_props 堆 Box,reset 时经追踪表统一释放;不登记则每个字面量泄漏一个 Box。
|
||||
#[test]
|
||||
fn new_object_literal_tracked_and_freed_on_reset() {
|
||||
let mut vm = Vm::new();
|
||||
let result = run_source(
|
||||
&mut vm,
|
||||
"var o = {}; for (var i = 0; i < 40; i++) { o['k' + i] = i; } \
|
||||
delete o.k7; o.k8",
|
||||
);
|
||||
assert_eq!(format!("{}", result), "8", "属性写入/删除后读取应正常");
|
||||
assert!(vm.epoch_object_count() > 0, "NEW_OBJECT 应登记 epoch 追踪表");
|
||||
|
||||
let freed_before = vm.session_gc_stats().total_bytes_freed;
|
||||
vm.reset();
|
||||
assert!(
|
||||
vm.session_gc_stats().total_bytes_freed > freed_before,
|
||||
"reset 应释放字面量对象的属性向量堆数据"
|
||||
);
|
||||
assert_eq!(vm.epoch_object_count(), 0, "reset 后追踪表应清空");
|
||||
}
|
||||
|
||||
/// full_reset 同样释放 NEW_OBJECT 字面量:带属性写的 epoch 源对象经 promote 深拷贝
|
||||
/// 到 session 后,完全重置同时释放源对象与克隆的堆数据,不得双重释放。
|
||||
#[test]
|
||||
fn new_object_literal_freed_by_full_reset() {
|
||||
let mut vm = Vm::new();
|
||||
let result = run_source(
|
||||
&mut vm,
|
||||
"var o = {}; for (var i = 0; i < 40; i++) { o['k' + i] = i; } \
|
||||
globalThis.keep = o; o.k7",
|
||||
);
|
||||
assert_eq!(format!("{}", result), "7", "逃逸后属性读取应正常");
|
||||
assert!(vm.epoch_object_count() > 0, "字面量源对象在 promote 后仍登记于 epoch 追踪表");
|
||||
assert!(vm.session_object_count() > 0, "逃逸克隆应登记于 session 追踪表");
|
||||
|
||||
vm.full_reset();
|
||||
assert_eq!(vm.epoch_object_count(), 0, "full_reset 后 epoch 追踪表应清空");
|
||||
assert_eq!(vm.session_object_count(), 0, "full_reset 后 session 追踪表应清空");
|
||||
assert!(
|
||||
run_source(&mut vm, "globalThis.keep").is_undefined(),
|
||||
"full_reset 后逃逸对象不可再访问"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user