style: 修 rustfmt 格式化差异

This commit is contained in:
2026-10-07 17:14:42 +00:00
parent 3fc6e86f64
commit 372bb80cfd
29 changed files with 250 additions and 159 deletions
+17 -5
View File
@@ -88,7 +88,8 @@ impl Vm {
&mut self, callee: JsValue, this_value: JsValue, args: &[JsValue], promise: JsValue, resolve: JsValue,
reject: JsValue,
) -> JsValue {
let proto_val = JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let proto_val =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
let obj = unsafe { &mut *ptr };
obj.type_tag = JsObject::OBJ_TYPE_ASYNC;
@@ -607,13 +608,20 @@ pub(crate) fn init_async_intrinsics(vm: &mut Vm) {
let af_ctor_fn_ptr =
unsafe { NativeFnPtr::from_raw(oxide_builtins::function::async_function_constructor::<Vm> as *const ()) };
let (af_ctor_ptr, af_ctor_is_new) =
match vm.realm.session.borrow().builtin_world().find_fn_wrapper(af_reuse_key, af_ctor_fn_ptr, 1) {
match vm
.realm
.session
.borrow()
.builtin_world()
.find_fn_wrapper(af_reuse_key, af_ctor_fn_ptr, 1)
{
Some(ptr) => (ptr, false),
None => {
// [[Prototype]] = Function 构造器本体(与 Function 构造器同链,
// `Object.getPrototypeOf(AsyncFunction) === Function` 语义)。
let fn_ctor_val =
JsValue::from_js_object(vm.realm.session.borrow().builtin_world().function_constructor.as_ptr() as *mut JsObject);
let fn_ctor_val = JsValue::from_js_object(
vm.realm.session.borrow().builtin_world().function_constructor.as_ptr() as *mut JsObject,
);
let mut af_ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, fn_ctor_val));
af_ctor.set_function(true);
af_ctor.set_native_arg_count(1);
@@ -638,7 +646,11 @@ pub(crate) fn init_async_intrinsics(vm: &mut Vm) {
af_ctor.set_shape_id(tag_shape);
let af_ctor_ptr = Box::into_raw(af_ctor);
// 登记进 world 释放表(带复用键):session 收尾统一释放构造器本体与属性区。
vm.realm.session.borrow().builtin_world().track_fn_wrapper(af_ctor_ptr, af_reuse_key);
vm.realm
.session
.borrow()
.builtin_world()
.track_fn_wrapper(af_ctor_ptr, af_reuse_key);
(af_ctor_ptr, true)
}
};
+6 -3
View File
@@ -103,7 +103,8 @@ impl Vm {
pub(crate) fn create_async_generator_object(
&mut self, callee: JsValue, this_value: JsValue, args: &[JsValue],
) -> Result<JsValue, String> {
let gen_proto_val = JsValue::from_js_object(self.realm.async_generator_proto.borrow().as_ptr() as *mut JsObject);
let gen_proto_val =
JsValue::from_js_object(self.realm.async_generator_proto.borrow().as_ptr() as *mut JsObject);
let obj = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, gen_proto_val));
let obj_ref = unsafe { &mut *obj };
obj_ref.type_tag = JsObject::OBJ_TYPE_ASYNC_GENERATOR;
@@ -1604,7 +1605,8 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
let proto2_si = sf.intern("prototype").0;
let proto2_shape = sh.make_shape(agf_proto.shape_id(), proto2_si);
agf_proto.set_shape_id(proto2_shape);
let ppos2 = agf_proto.push_prop(JsValue::from_js_object(vm.realm.async_generator_proto.borrow().as_ptr() as *mut JsObject));
let ppos2 =
agf_proto.push_prop(JsValue::from_js_object(vm.realm.async_generator_proto.borrow().as_ptr() as *mut JsObject));
agf_proto.set_data_meta(ppos2, PropAttributes::new(false, false, true));
// agf_proto[Symbol.toStringTag] = "AsyncGeneratorFunction"(数据属性,w/e/c = false/false/true)。
let tag2_key = oxide_types::private_key::encode_symbol_key(
@@ -1624,7 +1626,8 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
// SAFETY: agf_ctor_ptr 为 Box 原分配(已登记释放表、生命周期覆盖 session),本 Vm 独占。
unsafe {
let ctor_mut = &mut *agf_ctor_ptr;
let proto_val = JsValue::from_js_object(vm.realm.async_generator_function_proto.borrow().as_ptr() as *mut JsObject);
let proto_val =
JsValue::from_js_object(vm.realm.async_generator_function_proto.borrow().as_ptr() as *mut JsObject);
let name_val = JsValue::perm_string(sf.string_ptr(sf.intern("AsyncGeneratorFunction").0));
if agf_ctor_is_new {
let lpos = ctor_mut.push_prop(JsValue::int(1));
@@ -256,7 +256,10 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
core,
session,
shared_proto,
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG),
oxide_types::private_key::encode_symbol_key(
realm_id,
oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG,
),
"get [Symbol.toStringTag]",
oxide_builtins::typed_array::typed_array_to_string_tag_getter::<crate::vm::Vm> as *const (),
);
+4 -2
View File
@@ -89,8 +89,10 @@ pub fn bind_weak_map(core: &Arc<KernelCore>, session: &mut KernelSession, global
proto.ensure_hash_props().push(JsValue::from_js_object(ctor_ptr));
let ctor_pos = proto.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
proto.set_data_meta(ctor_pos, PropAttributes::new(true, false, true));
let tag_key =
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG);
let tag_key = oxide_types::private_key::encode_symbol_key(
realm_id,
oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG,
);
let tag_shape = core.shape_forge().make_shape(proto.shape_id(), tag_key);
proto.set_shape_id(tag_shape);
proto.ensure_hash_props().push(JsValue::perm_string(
+8 -4
View File
@@ -510,8 +510,10 @@ fn bind_iterator_protos(core: &Arc<KernelCore>, session: &KernelSession, realm_i
oxide_builtins::iterator::iterator_constructor_setter::<crate::vm::Vm> as *const (),
);
}
let sym_to_string_tag =
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG);
let sym_to_string_tag = oxide_types::private_key::encode_symbol_key(
realm_id,
oxide_types::private_key::WELL_KNOWN_SYMBOL_TO_STRING_TAG,
);
if core
.shape_forge()
.lookup_position(iter_proto.shape_id(), sym_to_string_tag)
@@ -603,8 +605,10 @@ fn bind_iterator_protos(core: &Arc<KernelCore>, session: &KernelSession, realm_i
realm_id,
);
}
let sym_adispose =
oxide_types::private_key::encode_symbol_key(realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_ASYNC_DISPOSE);
let sym_adispose = oxide_types::private_key::encode_symbol_key(
realm_id,
oxide_types::private_key::WELL_KNOWN_SYMBOL_ASYNC_DISPOSE,
);
if core
.shape_forge()
.lookup_position(aiter_proto.shape_id(), sym_adispose)
+2 -1
View File
@@ -892,7 +892,8 @@ pub(crate) fn init_generator_intrinsics(vm: &mut Vm) {
let proto2_si = sf.intern("prototype").0;
let proto2_shape = sh.make_shape(gf_proto.shape_id(), proto2_si);
gf_proto.set_shape_id(proto2_shape);
let ppos2 = gf_proto.push_prop(JsValue::from_js_object(vm.realm.generator_proto.borrow().as_ptr() as *mut JsObject));
let ppos2 =
gf_proto.push_prop(JsValue::from_js_object(vm.realm.generator_proto.borrow().as_ptr() as *mut JsObject));
gf_proto.set_data_meta(ppos2, oxide_types::object::PropAttributes::new(false, false, true));
// gf_proto[Symbol.toStringTag] = "GeneratorFunction"(数据属性,w/e/c = false/false/true)。
let tag2_key = oxide_types::private_key::encode_symbol_key(
+27 -13
View File
@@ -25,7 +25,8 @@ impl Vm {
/// 创建聚合静态方法(all/race/allSettled/any)的共享记录对象:剩余计数
/// 初始 1,结果数组(race 无)与能力 resolve/reject 闭包全部存为自身属性。
fn make_agg_record(&mut self, values: JsValue, resolve: JsValue, reject: JsValue) -> JsValue {
let proto_val = JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let proto_val =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;本次 native 调用内不搬移,借出期间无别名。
let obj = unsafe { &mut *ptr };
@@ -43,7 +44,8 @@ impl Vm {
/// 创建 keyed 聚合静态方法的共享记录对象:剩余计数(初始 1)、结果平行数组、
/// 键平行数组与能力 resolve/reject 闭包存为自身属性。
fn make_agg_record_keyed(&mut self, values: JsValue, keys: JsValue, resolve: JsValue, reject: JsValue) -> JsValue {
let proto_val = JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let proto_val =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;本次 native 调用内不搬移,借出期间无别名。
let obj = unsafe { &mut *ptr };
@@ -96,7 +98,8 @@ impl Vm {
/// 构造 allSettled 的结算记录 `{status, <value_field>: value}` 普通对象。
fn make_settled_record(&mut self, status: &str, value_field: &str, value: JsValue) -> JsValue {
let proto_val = JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let proto_val =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;写 status/value 属性(含 new_string 分配)期间不搬移,借出期间无别名。
let obj = unsafe { &mut *ptr };
@@ -132,7 +135,8 @@ impl Vm {
/// 把 errors 可迭代值收集为新数组(IterableToList)。不可迭代抛 TypeError。
fn aggregate_errors_to_list(&mut self, errors: JsValue) -> Result<JsValue, JsValue> {
let array_proto = JsValue::from_js_object(self.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject);
let array_proto =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject);
let ptr = self.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, array_proto, 0));
let list = JsValue::from_js_object(ptr);
let mut index = 0usize;
@@ -148,7 +152,8 @@ impl Vm {
/// 建普通数组对象并依次写入元素(Promise.try 转发实参的承载)。
fn make_plain_array(&mut self, elements: Vec<JsValue>) -> JsValue {
let array_proto = JsValue::from_js_object(self.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject);
let array_proto =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject);
let ptr = self.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, array_proto, 0));
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;元素写入不搬移对象。
let obj = unsafe { &mut *ptr };
@@ -210,8 +215,9 @@ impl Vm {
proto.set_data_meta(msg_pos, PropAttributes::new(true, false, true));
// %AggregateError% 构造器:proto = %Error%(NativeError 构造器继承 Error 构造器),length 2。
let error_ctor_val =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().error_constructor.as_ptr() as *mut JsObject);
let error_ctor_val = JsValue::from_js_object(
self.realm.session.borrow().builtin_world().error_constructor.as_ptr() as *mut JsObject,
);
let mut ctor = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_ctor_val));
ctor.set_function(true);
ctor.type_tag = JsObject::OBJ_TYPE_CONSTRUCTOR;
@@ -239,18 +245,24 @@ impl Vm {
Self::swap_intrinsic_proto(&mut self.realm.aggregate_error_constructor.borrow_mut(), *ctor);
// SAFETY: aggregate_error_proto 为堆址固定的 P<JsObject>(Arc 透明包装),本行前刚经 swap_intrinsic_proto 落地;与 ctor_mut 分属不同对象,无别名。
let proto_mut = unsafe { &mut *self.realm.aggregate_error_proto.borrow().as_mut_ptr() };
proto_mut
.set_prop_at(0u32, JsValue::from_js_object(self.realm.aggregate_error_constructor.borrow().as_ptr() as *mut JsObject));
proto_mut.set_prop_at(
0u32,
JsValue::from_js_object(self.realm.aggregate_error_constructor.borrow().as_ptr() as *mut JsObject),
);
// SAFETY: aggregate_error_constructor 同为堆址固定的 P<JsObject>(Arc 透明包装);此处写 prototype 槽位(下标 2),与 proto_mut 分属不同对象,无别名。
let ctor_mut = unsafe { &mut *self.realm.aggregate_error_constructor.borrow().as_mut_ptr() };
ctor_mut.set_prop_at(2u32, JsValue::from_js_object(self.realm.aggregate_error_proto.borrow().as_ptr() as *mut JsObject));
ctor_mut.set_prop_at(
2u32,
JsValue::from_js_object(self.realm.aggregate_error_proto.borrow().as_ptr() as *mut JsObject),
);
// 绑定 global(槽已存在则更新)。
let global_ptr = self.realm.session.borrow().global_object().as_ptr() as *mut JsObject;
// SAFETY: global 对象由 session 持有,存活整个 session;本函数内只改其 shape/属性区,期间无 reset 或对象搬移。
let global = unsafe { &mut *global_ptr };
let si = self.kernel_core.perm_interner().intern("AggregateError").0;
let ctor_val = JsValue::from_js_object(self.realm.aggregate_error_constructor.borrow().as_ptr() as *mut JsObject);
let ctor_val =
JsValue::from_js_object(self.realm.aggregate_error_constructor.borrow().as_ptr() as *mut JsObject);
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(global.shape_id(), si) {
global.set_prop_at(pos, ctor_val);
} else {
@@ -353,7 +365,8 @@ pub(super) fn promise_static_with_resolvers(vm: &mut Vm, args: &[u8]) -> NativeR
Ok(t) => t,
Err(err) => return NativeResult::Err(err),
};
let object_proto = JsValue::from_js_object(vm.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let object_proto =
JsValue::from_js_object(vm.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let ptr = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, object_proto));
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;写 promise/resolve/reject 属性期间不搬移,借出期间无别名。
let obj = unsafe { &mut *ptr };
@@ -478,7 +491,8 @@ fn perform_promise_combine(
let values = if kind == AggregateKind::Race {
JsValue::undefined()
} else {
let array_proto = JsValue::from_js_object(vm.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject);
let array_proto =
JsValue::from_js_object(vm.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject);
let ptr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, array_proto, 0));
JsValue::from_js_object(ptr)
};
+11 -5
View File
@@ -117,8 +117,9 @@ impl Vm {
self.realm.session.borrow().builtin_world().data_view_constructor.as_ptr() as *mut JsObject,
);
let this_val = if is_data_view {
let data_view_proto_val =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().data_view_proto.as_ptr() as *mut JsObject);
let data_view_proto_val = JsValue::from_js_object(
self.realm.session.borrow().builtin_world().data_view_proto.as_ptr() as *mut JsObject,
);
JsValue::from_js_object(self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, data_view_proto_val)))
} else {
let this_ptr = self.alloc_ctor_this(nt_obj, ctor_obj, new_target)?;
@@ -156,7 +157,8 @@ impl Vm {
&mut self, nt_obj: &JsObject, ctor_obj: &JsObject, nt_val: JsValue,
) -> Result<*mut JsObject, JsValue> {
let proto_si = self.kernel_core.perm_interner().intern("prototype").0;
let object_proto = JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let object_proto =
JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let is_native_ctor = ctor_obj.native_fn().is_some() && ctor_obj.type_tag == JsObject::OBJ_TYPE_CONSTRUCTOR;
let proto_val = if is_native_ctor {
match self.resolve_property(nt_obj, proto_si) {
@@ -337,12 +339,16 @@ impl Vm {
// SAFETY: `promise_proto` 为 `P<JsObject>`(Arc 透明包装),堆址固定且本行前刚经
// swap_intrinsic_proto 落地;与下一处 ctor_mut 指向不同对象,无别名。
let proto_mut = unsafe { &mut *self.realm.promise_proto.borrow().as_mut_ptr() };
proto_mut.set_prop_at(0u32, JsValue::from_js_object(self.realm.promise_constructor.borrow().as_ptr() as *mut JsObject));
proto_mut.set_prop_at(
0u32,
JsValue::from_js_object(self.realm.promise_constructor.borrow().as_ptr() as *mut JsObject),
);
// SAFETY: `promise_constructor` 同为堆址固定的存活 `P<JsObject>`(Arc 透明包装);
// 此处写 prototype 槽位(下标 2),与 proto_mut 分属不同对象,无别名。
let ctor_mut = unsafe { &mut *self.realm.promise_constructor.borrow().as_mut_ptr() };
// prototype 槽位在 length/name 之后(下标 2)。
ctor_mut.set_prop_at(2u32, JsValue::from_js_object(self.realm.promise_proto.borrow().as_ptr() as *mut JsObject));
ctor_mut
.set_prop_at(2u32, JsValue::from_js_object(self.realm.promise_proto.borrow().as_ptr() as *mut JsObject));
// Promise[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链
// 解析 @@species 得自身构造器。ctor 经本函数每次调用全新构造,同键槽不累积。
+16 -2
View File
@@ -774,7 +774,14 @@ impl SessionGc {
/// forwarding 表与根指针重写。在字符串清扫之后运行。
/// 返回释放的字节数。
pub(crate) fn sweep_session_bigints(&mut self, vm: &mut Vm) -> u64 {
let old = vm.realm.gc.borrow_mut().session_bigint_ptrs.borrow_mut().drain(..).collect::<Vec<_>>();
let old = vm
.realm
.gc
.borrow_mut()
.session_bigint_ptrs
.borrow_mut()
.drain(..)
.collect::<Vec<_>>();
let mut freed = 0u64;
let mut live = Vec::with_capacity(old.len());
for ptr in old {
@@ -809,7 +816,14 @@ impl SessionGc {
/// 统计、不重算存活账目。
/// 返回释放的字节数。
pub(crate) fn sweep_session_cells(&mut self, vm: &mut Vm) -> u64 {
let old = vm.realm.gc.borrow_mut().session_cell_ptrs.borrow_mut().drain(..).collect::<Vec<_>>();
let old = vm
.realm
.gc
.borrow_mut()
.session_cell_ptrs
.borrow_mut()
.drain(..)
.collect::<Vec<_>>();
let mut freed = 0u64;
let mut live = Vec::with_capacity(old.len());
for ptr in old {
+20 -5
View File
@@ -563,7 +563,8 @@ fn weak_map_dead_key_freed_by_in_run_sweep() {
// 键无强根:仅表内弱边引用。
let key = plain_object(&mut vm);
// P 键(builtin 原型,不可死):对照条目须保留。
let p_key = JsValue::from_js_object(vm.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
let p_key =
JsValue::from_js_object(vm.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject);
unsafe {
oxide_builtins::weak_map::weak_map_insert(
&mut *wm,
@@ -1196,7 +1197,10 @@ fn live_closure_cell_survives_full_collect() {
collect(&mut vm);
// 只断言表成员——sweep 已释放的指针解引用即 UB。
assert!(vm.realm.gc.borrow().session_cell_ptrs.borrow().contains(&cell_ptr), "活 cell 应跨完整收集存活");
assert!(
vm.realm.gc.borrow().session_cell_ptrs.borrow().contains(&cell_ptr),
"活 cell 应跨完整收集存活"
);
}
/// 活跃帧 cell_stack 根:内层函数 upvalue cell 在活跃帧 cell_stack 上(低阈值使
@@ -1256,7 +1260,10 @@ fn suspended_state_box_cell_root_survives_collect() {
collect(&mut vm);
// 只断言表成员——sweep 已释放的指针解引用即 UB。
assert!(vm.realm.gc.borrow().session_cell_ptrs.borrow().contains(&cell_ptr), "挂起帧 cell 应跨完整收集存活");
assert!(
vm.realm.gc.borrow().session_cell_ptrs.borrow().contains(&cell_ptr),
"挂起帧 cell 应跨完整收集存活"
);
// 恢复后读值:cell 未被误释放。
let read = vm.run(&Arc::new(compile("globalThis.g.next().value"))).expect("read");
@@ -1394,7 +1401,12 @@ fn strings_only_collection_preserves_all_root_kinds() {
assert!(vm.realm.gc.borrow().session_string_ptrs.contains(&reg_str.as_string_ptr_mut()));
assert!(vm.realm.gc.borrow().session_string_ptrs.contains(&prop_str.as_string_ptr_mut()));
assert!(vm.realm.gc.borrow().session_string_ptrs.contains(&epoch_str.as_string_ptr_mut()));
assert!(vm
.realm
.gc
.borrow()
.session_string_ptrs
.contains(&epoch_str.as_string_ptr_mut()));
assert!(!vm.realm.gc.borrow().session_string_ptrs.contains(&dead_ptr));
// 存活串内容可读,地址稳定。
assert_eq!(unsafe { (*reg_str.as_string_ptr_mut()).as_str() }, "reg-root".repeat(16));
@@ -1713,7 +1725,10 @@ fn active_and_suspended_for_in_do_not_block_in_run_collection() {
vm.maybe_collect_in_run();
assert_eq!(vm.session_gc_stats().total_collections, 1, "无门控:活跃 for-in 存在时收集照常执行");
assert!(!vm.realm.gc.borrow().session_object_ptrs.contains(&dead), "死 session 对象应被原地释放并出表");
assert!(
!vm.realm.gc.borrow().session_object_ptrs.contains(&dead),
"死 session 对象应被原地释放并出表"
);
// 挂起形:生成器在 for-in 内 yield 后 run 结束,迭代器经状态盒持有
// (vm.iters 已空)——键经状态盒边入根收集标活,收集照常执行。
+10 -3
View File
@@ -93,7 +93,10 @@ impl Vm {
f(RootGroup::ExceptionValue, self.exception_value.unwrap_or(JsValue::undefined()));
f(RootGroup::PendingException, self.pending_exception.unwrap_or(JsValue::undefined()));
f(RootGroup::LastUncaught, self.last_uncaught_value.unwrap_or(JsValue::undefined()));
f(RootGroup::PendingLengthException, self.pending_length_exception.unwrap_or(JsValue::undefined()));
f(
RootGroup::PendingLengthException,
self.pending_length_exception.unwrap_or(JsValue::undefined()),
);
// 悬挂的 return 完成持有返回值,是 GC 根。
if let Some(Completion::Return { value, .. }) = self.pending_completion {
f(RootGroup::PendingCompletion, value);
@@ -150,7 +153,10 @@ impl Vm {
}
}
}
f(RootGroup::Global, JsValue::from_js_object(self.realm.session.borrow().global_object().as_ptr() as *mut JsObject));
f(
RootGroup::Global,
JsValue::from_js_object(self.realm.session.borrow().global_object().as_ptr() as *mut JsObject),
);
}
/// GC 根统一枚举入口:遍历的字段清单与 `for_each_value` 相同。
@@ -266,7 +272,8 @@ impl Vm {
// SAFETY: ptr 在字符串表登记,收尾前有效。
bytes += (std::mem::size_of::<JsString>() + unsafe { (*ptr).payload_bytes() }) as u64;
}
bytes += (self.realm.gc.borrow().session_bigint_ptrs.borrow().len() * std::mem::size_of::<num_bigint::BigInt>()) as u64;
bytes += (self.realm.gc.borrow().session_bigint_ptrs.borrow().len() * std::mem::size_of::<num_bigint::BigInt>())
as u64;
bytes += (self.realm.gc.borrow().session_cell_ptrs.borrow().len() * std::mem::size_of::<Cell>()) as u64;
bytes
}
+1 -4
View File
@@ -114,10 +114,7 @@ impl VmPool {
/// # 副作用
/// - 同步创建 `min_size` 个 Vm。
pub fn with_counters(
kernel_core: Arc<KernelCore>,
min_size: usize,
max_size: Option<usize>,
counters: Arc<PoolCounters>,
kernel_core: Arc<KernelCore>, min_size: usize, max_size: Option<usize>, counters: Arc<PoolCounters>,
) -> Arc<Self> {
let warm = min_size.min(max_size.unwrap_or(min_size));
let pool = Arc::new(Self {
+13 -9
View File
@@ -80,7 +80,10 @@ impl Vm {
aggregate_error_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_function_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_generator_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_generator_function_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_generator_function_proto: RefCell::new(P::new(JsObject::new_empty(
EMPTY_SHAPE_ID,
JsValue::null(),
))),
gc: RefCell::new(GcState {
session_gc: crate::session_gc::SessionGc::new(),
session_object_ptrs: Vec::new(),
@@ -230,7 +233,10 @@ impl Vm {
aggregate_error_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_function_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_generator_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_generator_function_proto: RefCell::new(P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))),
async_generator_function_proto: RefCell::new(P::new(JsObject::new_empty(
EMPTY_SHAPE_ID,
JsValue::null(),
))),
gc: RefCell::new(GcState {
session_gc: crate::session_gc::SessionGc::new(),
session_object_ptrs: Vec::new(),
@@ -400,9 +406,7 @@ impl Vm {
self.realm_id(),
);
}
*self.realm
.object_prototype
.borrow_mut() = P::clone(&self.realm.session.borrow().builtin_world().object_proto);
*self.realm.object_prototype.borrow_mut() = P::clone(&self.realm.session.borrow().builtin_world().object_proto);
self.init_generator_intrinsics();
self.init_promise_intrinsics();
self.init_async_intrinsics();
@@ -418,9 +422,7 @@ impl Vm {
pub fn full_reset_legacy_for_bench(&mut self) {
*self.realm.session.borrow_mut() = KernelSession::new(&self.kernel_core);
bindings::init_kernel_builtins(&self.kernel_core, &mut self.realm.session.borrow_mut(), self.realm_id());
*self.realm
.object_prototype
.borrow_mut() = P::clone(&self.realm.session.borrow().builtin_world().object_proto);
*self.realm.object_prototype.borrow_mut() = P::clone(&self.realm.session.borrow().builtin_world().object_proto);
self.init_generator_intrinsics();
self.init_promise_intrinsics();
self.init_async_intrinsics();
@@ -762,7 +764,9 @@ impl Vm {
} else if is_generator {
JsValue::from_js_object(self.realm.generator_proto.borrow().as_ptr() as *mut JsObject)
} else {
JsValue::from_js_object(self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject)
JsValue::from_js_object(
self.realm.session.borrow().builtin_world().object_proto.as_ptr() as *mut JsObject
)
};
// prototype 子对象与函数本体同走 session 分配:`f.prototype ===
// globalThis.f.prototype` 要求两侧同一对象,逃逸写不会克隆出第二份。
+44 -11
View File
@@ -288,7 +288,10 @@ fn full_reset_clean_keeps_session_objects() {
assert!(std::ptr::eq(world_ptr, Arc::as_ptr(&vm.realm.session.borrow().builtin_world)));
assert!(std::ptr::eq(global_ptr, vm.realm.session.borrow().global_object.as_ptr()));
assert!(std::ptr::eq(object_proto_ptr, vm.realm.session.borrow().builtin_world().object_proto.as_ptr()));
assert!(std::ptr::eq(
object_proto_ptr,
vm.realm.session.borrow().builtin_world().object_proto.as_ptr()
));
assert!(!vm.realm.session.borrow().is_dirty_since_snapshot());
}
@@ -326,8 +329,14 @@ fn full_reset_dirty_builtin_rebinds_global_slot() {
vm.full_reset();
assert!(std::ptr::eq(old_object_proto, vm.realm.session.borrow().builtin_world().object_proto.as_ptr()));
assert!(!std::ptr::eq(old_array_proto, vm.realm.session.borrow().builtin_world().array_proto.as_ptr()));
assert!(std::ptr::eq(
old_object_proto,
vm.realm.session.borrow().builtin_world().object_proto.as_ptr()
));
assert!(!std::ptr::eq(
old_array_proto,
vm.realm.session.borrow().builtin_world().array_proto.as_ptr()
));
assert!(std::ptr::eq(
global_prop(&vm, "Array").as_js_object_ptr(),
vm.realm.session.borrow().builtin_world().array_constructor.as_ptr() as *mut JsObject
@@ -599,7 +608,10 @@ fn full_reset_refreshes_object_prototype_after_object_dirty() {
vm.full_reset();
assert!(!std::ptr::eq(old_object_proto, vm.realm.session.borrow().builtin_world().object_proto.as_ptr()));
assert!(!std::ptr::eq(
old_object_proto,
vm.realm.session.borrow().builtin_world().object_proto.as_ptr()
));
assert!(std::ptr::eq(
vm.realm.object_prototype.borrow().as_ptr(),
vm.realm.session.borrow().builtin_world().object_proto.as_ptr()
@@ -618,8 +630,14 @@ fn full_reset_object_dirty_rebinds_iterator_family() {
vm.full_reset();
// object 家族与迭代器原型全部重建(新原型链到新 Object.prototype)。
assert!(!std::ptr::eq(old_object_proto, vm.realm.session.borrow().builtin_world().object_proto.as_ptr()));
assert!(!std::ptr::eq(old_iterator_proto, vm.realm.session.borrow().builtin_world().iterator_proto.as_ptr()));
assert!(!std::ptr::eq(
old_object_proto,
vm.realm.session.borrow().builtin_world().object_proto.as_ptr()
));
assert!(!std::ptr::eq(
old_iterator_proto,
vm.realm.session.borrow().builtin_world().iterator_proto.as_ptr()
));
// global 保留(dirty.global=false):其 Iterator 函数对象的 prototype
// 属性须对齐到重建后的 %IteratorPrototype%。
let iter_val = global_prop(&vm, "Iterator");
@@ -872,7 +890,10 @@ fn full_reset_value_overwrite_on_builtin_proto_rebuilds_family() {
vm.full_reset();
assert!(!std::ptr::eq(old_array_proto, vm.realm.session.borrow().builtin_world().array_proto.as_ptr()));
assert!(!std::ptr::eq(
old_array_proto,
vm.realm.session.borrow().builtin_world().array_proto.as_ptr()
));
let t = run_source(&mut vm, "typeof Array.prototype.push");
assert_eq!(vm.lookup_str(t).as_deref(), Some("function"));
assert_eq!(run_source(&mut vm, "[1, 2].push(3)"), JsValue::int(3));
@@ -892,7 +913,10 @@ fn full_reset_value_overwrite_with_object_value_drops_stale_pointer() {
vm.full_reset();
assert!(!std::ptr::eq(old_array_proto, vm.realm.session.borrow().builtin_world().array_proto.as_ptr()));
assert!(!std::ptr::eq(
old_array_proto,
vm.realm.session.borrow().builtin_world().array_proto.as_ptr()
));
let t = run_source(&mut vm, "typeof Array.prototype.push");
assert_eq!(vm.lookup_str(t).as_deref(), Some("function"));
assert!(!vm.realm.session.borrow().is_dirty_since_snapshot());
@@ -1028,7 +1052,10 @@ fn full_reset_global_function_wrapper_property_does_not_survive() {
let _ = run_source(&mut vm, "0");
let _ = run_source(&mut vm, "parseInt.custom = 1; 0");
assert!(vm.realm.session.borrow().is_dirty_since_snapshot(), "global 函数 wrapper 写应被脏检测捕获");
assert!(
vm.realm.session.borrow().is_dirty_since_snapshot(),
"global 函数 wrapper 写应被脏检测捕获"
);
vm.full_reset();
@@ -1080,7 +1107,10 @@ fn benign_user_object_writes_do_not_dirty_leaked_objects() {
vm.full_reset();
assert!(std::ptr::eq(world_ptr, Arc::as_ptr(&vm.realm.session.borrow().builtin_world)), "无污染不应重建 world");
assert!(
std::ptr::eq(world_ptr, Arc::as_ptr(&vm.realm.session.borrow().builtin_world)),
"无污染不应重建 world"
);
assert!(!vm.realm.session.borrow().is_dirty_since_snapshot());
}
@@ -1101,7 +1131,10 @@ fn benign_run_does_not_falsely_dirty_builtins() {
vm.full_reset();
assert!(std::ptr::eq(world_ptr, Arc::as_ptr(&vm.realm.session.borrow().builtin_world)), "builtin world 不应重建");
assert!(
std::ptr::eq(world_ptr, Arc::as_ptr(&vm.realm.session.borrow().builtin_world)),
"builtin world 不应重建"
);
assert!(!vm.realm.session.borrow().is_dirty_since_snapshot());
}