mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 补晋升域弱键定夺 in-run 钉与文档前提
This commit is contained in:
@@ -303,6 +303,12 @@ impl Vm {
|
||||
/// session 可见,后续完整 GC 的留存账目不再漏"仅驻留 epoch arena 的对象"。
|
||||
/// - 与 `promote_session_epoch_refs` 互补:本方法处理根直接持有的 epoch 对象,
|
||||
/// 后者处理 session 对象持有的 epoch 子引用(闭包捕获等绕过写屏障的来源)。
|
||||
/// - 弱键定夺(`rewrite_weak_map_keys_after_promotion`)只按根直接子树的
|
||||
/// 转发表为判据:经 session 对象(非根)强持的 epoch 键不在表内会被判死
|
||||
/// 丢条目,而本调用不释放 epoch——键强存活时条目即消失。配对调用
|
||||
/// (随后 `promote_session_epoch_refs`)由第二趟收敛转发表,但第一趟已丢
|
||||
/// 条目不可复原;独立调用须根直接子树已覆盖全部强可达 epoch 对象
|
||||
/// (即不存在经 session 对象强持的弱键)方为合法时机。
|
||||
pub fn promote_rooted_epoch_objects(&mut self) {
|
||||
let mut epoch_roots = Vec::new();
|
||||
self.for_each_root(|value| {
|
||||
|
||||
@@ -370,6 +370,13 @@ impl SessionGc {
|
||||
}
|
||||
}
|
||||
}
|
||||
if obj.is_weak_map_obj() {
|
||||
for value in weak_map::weak_map_native_edges(obj) {
|
||||
if value.is_string() {
|
||||
Self::mark_string_live(live, value.as_string_ptr_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
if obj.is_module_namespace() {
|
||||
for value in module::module_ns_native_edges(obj) {
|
||||
if value.is_string() {
|
||||
|
||||
@@ -624,6 +624,79 @@ fn weak_map_value_edge_keeps_value_alive() {
|
||||
assert_eq!(vm.gc_state.session_object_ptrs.len(), 2);
|
||||
}
|
||||
|
||||
/// in-run 晋升定夺·死键面:无强根的 epoch 键经收敛后转发表判死丢条目;
|
||||
/// P 键不可死,条目保留且按原键读回。
|
||||
#[test]
|
||||
fn weak_map_dead_epoch_key_dropped_by_in_run_promotion() {
|
||||
let mut vm = vm_with_threshold(65536);
|
||||
let value = plain_object(&mut vm);
|
||||
let wm = weak_map_object(&mut vm);
|
||||
// 键无强根:仅表内弱边引用。
|
||||
let key = plain_object(&mut vm);
|
||||
// P 键(builtin 原型,不可死):对照条目须保留。
|
||||
let p_key = JsValue::from_js_object(vm.session.builtin_world().object_proto.as_ptr() as *mut JsObject);
|
||||
unsafe {
|
||||
oxide_builtins::weak_map::weak_map_insert(
|
||||
&mut *wm,
|
||||
JsValue::from_js_object(key),
|
||||
JsValue::from_js_object(value),
|
||||
);
|
||||
oxide_builtins::weak_map::weak_map_insert(&mut *wm, p_key, JsValue::int(7));
|
||||
}
|
||||
// 探针对象绕过 alloc_object,手动登记 epoch 表(in-run 档按表晋升与释放)。
|
||||
vm.gc_state.epoch_object_ptrs.push(wm);
|
||||
vm.gc_state.epoch_object_ptrs.push(key);
|
||||
vm.gc_state.epoch_object_ptrs.push(value);
|
||||
vm.regs[0] = JsValue::from_js_object(wm);
|
||||
vm.regs[2] = JsValue::from_js_object(value);
|
||||
vm.maybe_collect_in_run();
|
||||
|
||||
assert_eq!(vm.session_gc_stats().total_collections, 1, "in-run 收集应跑一轮");
|
||||
let live_wm = unsafe { &*vm.regs[0].as_js_object_ptr() };
|
||||
assert_eq!(oxide_builtins::weak_map::weak_map_entry_count(live_wm), 1, "死键条目须丢、P 键条目须留");
|
||||
assert_eq!(
|
||||
oxide_builtins::weak_map::weak_map_probe_get(live_wm, p_key),
|
||||
JsValue::int(7),
|
||||
"P 键条目须按原键读回"
|
||||
);
|
||||
}
|
||||
|
||||
/// in-run 晋升定夺·活键面:强可达 epoch 键入收敛后转发表,条目键改指克隆、
|
||||
/// 值边改指后按新键读回同一克隆。
|
||||
#[test]
|
||||
fn weak_map_live_epoch_key_repointed_by_in_run_promotion() {
|
||||
let mut vm = vm_with_threshold(65536);
|
||||
let key = plain_object(&mut vm);
|
||||
let value = plain_object(&mut vm);
|
||||
let wm = weak_map_object(&mut vm);
|
||||
unsafe {
|
||||
oxide_builtins::weak_map::weak_map_insert(
|
||||
&mut *wm,
|
||||
JsValue::from_js_object(key),
|
||||
JsValue::from_js_object(value),
|
||||
);
|
||||
}
|
||||
// 探针对象绕过 alloc_object,手动登记 epoch 表(in-run 档按表晋升与释放)。
|
||||
vm.gc_state.epoch_object_ptrs.push(wm);
|
||||
vm.gc_state.epoch_object_ptrs.push(key);
|
||||
vm.gc_state.epoch_object_ptrs.push(value);
|
||||
vm.regs[0] = JsValue::from_js_object(wm);
|
||||
vm.regs[1] = JsValue::from_js_object(key);
|
||||
vm.regs[2] = JsValue::from_js_object(value);
|
||||
vm.maybe_collect_in_run();
|
||||
|
||||
let live_wm = unsafe { &*vm.regs[0].as_js_object_ptr() };
|
||||
assert!(live_wm.is_session_epoch(), "in-run 收集后弱表应晋升 session");
|
||||
assert_eq!(
|
||||
oxide_builtins::weak_map::weak_map_entry_count(live_wm),
|
||||
1,
|
||||
"强可达键的条目须在 in-run 定夺后存活"
|
||||
);
|
||||
let stored = oxide_builtins::weak_map::weak_map_probe_get(live_wm, vm.regs[1]);
|
||||
assert_eq!(stored, vm.regs[2], "值须按改指后的键读回同一克隆");
|
||||
assert!(vm.is_session_ptr(stored.as_js_object_ptr()), "值边须改指 session 克隆");
|
||||
}
|
||||
|
||||
/// 盒持唯一引用的 session 串与 BigInt 经 Map native 边进入存活集:
|
||||
/// 清寄存器仅留 Map 根后完整收集,两值仍登记在 session 表。
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user