mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
refactor: 退役内置盒克隆重写族死函数与孤儿辅助
This commit is contained in:
@@ -144,8 +144,8 @@ fn dv_buffer_writable<H: VmHost>(vm: &mut H, view: DataViewData) -> Result<(), J
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// JS 调用点后的缓冲重取纪律:重读寄存器再重取载荷(epoch 晋升改写
|
||||
/// 寄存器,旧 JsValue 滞留 epoch 克隆旧盒);detached → TypeError。
|
||||
/// JS 调用点后的缓冲重取纪律:重读寄存器并重取载荷,寄存器值为唯一口径;
|
||||
/// detached → TypeError。
|
||||
/// 返回(寄存器重读值、live 长、存储上限)。
|
||||
fn revalidate_buffer<H: VmHost>(vm: &mut H, buf_reg: u8) -> Result<(JsValue, usize, usize), JsValue> {
|
||||
let buffer = vm.reg(buf_reg);
|
||||
@@ -246,8 +246,7 @@ fn has_data_view_proto<H: VmHost>(vm: &mut H, this_val: JsValue) -> bool {
|
||||
/// # 边界与前提
|
||||
/// - 原型读取在全部初校验之后:越界 RangeError 先于抛错的 prototype getter。
|
||||
/// - NewTarget 非对象(直调/缺省面)时直接回落默认原型,不抛错。
|
||||
/// - 每个 JS 调用点后重取缓冲(重读寄存器 + 载荷重取):晋升改写寄存器,
|
||||
/// 旧值滞留 epoch 克隆旧盒。
|
||||
/// - 每个 JS 调用点后重取缓冲(重读寄存器 + 载荷重取),寄存器值为唯一口径。
|
||||
pub fn data_view_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !has_data_view_proto(vm, this_val) {
|
||||
@@ -357,39 +356,6 @@ pub fn data_view_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 克隆 DataView 视图数据到新对象,用 `rewrite` 改写 buffer 引用。
|
||||
pub fn clone_data_view_native_with_rewrite<F>(old_obj: &JsObject, new_obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
let Some(ptr) = data_view_data_ptr(old_obj) else {
|
||||
return;
|
||||
};
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
let mut data = unsafe { *ptr };
|
||||
data.buffer = rewrite(data.buffer);
|
||||
let cloned = Box::into_raw(Box::new(data));
|
||||
new_obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(cloned as *const ()) }));
|
||||
}
|
||||
|
||||
/// 原地重写 DataView 的 buffer 引用。
|
||||
pub fn rewrite_data_view_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
let Some(ptr) = data_view_data_ptr(obj) else {
|
||||
return;
|
||||
};
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
(*ptr).buffer = rewrite((*ptr).buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读核算 DataView 视图数据字节(不释放)。
|
||||
pub fn data_view_native_size(obj: &JsObject) -> u64 {
|
||||
let Some(ptr) = data_view_data_ptr(obj) else {
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
//! `type_tag` 为 `JsObject::OBJ_TYPE_DISPOSABLE_STACK`(同步)或
|
||||
//! `OBJ_TYPE_ASYNC_DISPOSABLE_STACK`(异步)时区分接收者,`hint` 以 0/1 两值区分
|
||||
//! 条目释放语义(定义见 `DisposeEntry.hint`),`wrap_sync` 标记 async 栈 use 落回
|
||||
//! `@@dispose` 的条目(返回值丢弃、异常异步化)。GC 四函数
|
||||
//! (edges/rewrite/clone/drop)供 session 层跨 epoch 追踪,签名与 Map/Promise
|
||||
//! `@@dispose` 的条目(返回值丢弃、异常异步化)。GC 三函数
|
||||
//! (edges/size/drop)接线 mark 边、字节账目与释放,形态与 Map/Promise
|
||||
//! 状态盒同构。
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
@@ -579,60 +579,6 @@ pub fn dispose_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
unsafe { (*ptr).entries.iter().flat_map(|entry| [entry.value, entry.method]).collect() }
|
||||
}
|
||||
|
||||
/// 克隆状态盒到新对象,用 `rewrite` 改写其中的对象引用
|
||||
/// (供跨 epoch 的对象重写/克隆流程使用)。
|
||||
pub fn clone_dispose_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !src.is_disposable_stack_obj() && !src.is_async_disposable_stack_obj() {
|
||||
return;
|
||||
}
|
||||
let ptr = get_capability_ptr(src);
|
||||
if ptr.is_null() {
|
||||
dst.set_native_data(std::ptr::null_mut());
|
||||
return;
|
||||
}
|
||||
// SAFETY: 同上,src 状态盒在 GC 移动期间仍存活。
|
||||
let src_cap = unsafe { &*ptr };
|
||||
let cloned = DisposeCapability {
|
||||
state: src_cap.state,
|
||||
entries: src_cap
|
||||
.entries
|
||||
.iter()
|
||||
.map(|entry| DisposeEntry {
|
||||
value: if entry.value.is_object() { rewrite(entry.value) } else { entry.value },
|
||||
method: if entry.method.is_object() { rewrite(entry.method) } else { entry.method },
|
||||
hint: entry.hint,
|
||||
arg_style: entry.arg_style,
|
||||
wrap_sync: entry.wrap_sync,
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
dst.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
|
||||
}
|
||||
|
||||
/// 原地重写状态盒,用 `rewrite` 改写其中的对象引用。
|
||||
pub fn rewrite_dispose_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !obj.is_disposable_stack_obj() && !obj.is_async_disposable_stack_obj() {
|
||||
return;
|
||||
}
|
||||
let ptr = get_capability_ptr(obj);
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
// SAFETY: 同上,改写发生在 GC 移动/清扫期间,对象仍存活。
|
||||
unsafe {
|
||||
for entry in &mut (*ptr).entries {
|
||||
entry.value = rewrite(entry.value);
|
||||
entry.method = rewrite(entry.method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读核算 DisposableStack 状态盒字节(不释放)。
|
||||
pub fn disposable_stack_native_size(obj: &JsObject) -> u64 {
|
||||
if !obj.is_disposable_stack_obj() && !obj.is_async_disposable_stack_obj() {
|
||||
|
||||
@@ -41,13 +41,6 @@ impl MapInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
slots: Vec::with_capacity(capacity),
|
||||
index: HashMap::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
/// 活表条目数(规范 SetDataSize 口径,空槽不计)。
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
self.index.len()
|
||||
@@ -171,54 +164,6 @@ pub fn map_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
unsafe { (*inner).iter().flat_map(|(key, value)| [key.0, value]).collect() }
|
||||
}
|
||||
|
||||
/// 克隆 Map 的 native 数据到新对象,用 `rewrite` 改写其中的对象引用
|
||||
/// (供跨 epoch 的对象重写/克隆流程使用)。
|
||||
pub fn clone_map_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !src.is_map() {
|
||||
return;
|
||||
}
|
||||
let inner = src.native_data() as *const MapInner;
|
||||
if inner.is_null() {
|
||||
dst.set_native_data(std::ptr::null_mut());
|
||||
return;
|
||||
}
|
||||
let mut cloned = MapInner::new();
|
||||
unsafe {
|
||||
for (key, value) in (*inner).iter() {
|
||||
let new_key = if key.0.is_object() { SetKey(rewrite(key.0)) } else { key };
|
||||
let new_value = if value.is_object() { rewrite(value) } else { value };
|
||||
cloned.insert(new_key, new_value);
|
||||
}
|
||||
}
|
||||
dst.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
|
||||
}
|
||||
|
||||
/// 原地重写 Map 的 native 数据,用 `rewrite` 改写其中的对象引用。
|
||||
pub fn rewrite_map_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !obj.is_map() {
|
||||
return;
|
||||
}
|
||||
let inner = obj.native_data() as *mut MapInner;
|
||||
if inner.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
let mut rewritten = MapInner::with_capacity((*inner).len());
|
||||
for (key, value) in (*inner).iter() {
|
||||
let new_key = if key.0.is_object() { SetKey(rewrite(key.0)) } else { key };
|
||||
let new_value = if value.is_object() { rewrite(value) } else { value };
|
||||
rewritten.insert(new_key, new_value);
|
||||
}
|
||||
*inner = rewritten;
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读核算 Map 的 native 数据字节(不释放)。
|
||||
/// 槽表与辅助索引均按 capacity 核算,与 `drop_map_native` 释放口径一致,
|
||||
/// 供 GC 账目核算。
|
||||
|
||||
@@ -235,79 +235,6 @@ pub fn module_ns_cell_edges(obj: &JsObject) -> Vec<*mut Cell> {
|
||||
out
|
||||
}
|
||||
|
||||
/// 原地重写条目表内的 JsValue 边(对象搬移/epoch 晋升后的引用重定位)。
|
||||
///
|
||||
/// # 副作用
|
||||
/// - 改写 `Value` 条目的值与共享 cell 内的值;cell 指针本身稳定不变。
|
||||
pub fn rewrite_module_ns_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
let table = ns_table_ptr(obj);
|
||||
if table.is_null() {
|
||||
return;
|
||||
}
|
||||
// SAFETY: table 归本 ns 对象持有,原地改写其 JsValue 边。
|
||||
let table_ref = unsafe { &mut *table };
|
||||
for entry in table_ref.entries.iter_mut() {
|
||||
match &mut entry.state {
|
||||
ModuleNsState::Value { value, .. } => *value = rewrite(*value),
|
||||
ModuleNsState::Cell(cell) => {
|
||||
if !cell.is_null() {
|
||||
// SAFETY: cell 生命周期见 `module_ns_export`;共享 cell 内值一并改写。
|
||||
let cell_ref = unsafe { &mut **cell };
|
||||
cell_ref.value = rewrite(cell_ref.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 深拷贝条目表到 `dst`,并用 `rewrite` 改写其中的对象引用。
|
||||
///
|
||||
/// # 注意事项
|
||||
/// - `clone_for_session_epoch` 只浅拷贝 `native_data` 指针;本函数必须在新对象上
|
||||
/// 重建独立 Box,否则原件与克隆共享同一表会在释放时双放。
|
||||
/// - `Cell` 指针本身跨搬移稳定,只改写其内部值。
|
||||
pub fn clone_module_ns_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !src.is_module_namespace() {
|
||||
return;
|
||||
}
|
||||
let table = src.native_data() as *const ModuleNsTable;
|
||||
if table.is_null() {
|
||||
dst.set_native_data(std::ptr::null_mut());
|
||||
return;
|
||||
}
|
||||
// SAFETY: src.native_data 指向 src 持有的 Box<ModuleNsTable>。
|
||||
let table_ref = unsafe { &*table };
|
||||
let mut entries = Vec::with_capacity(table_ref.entries.len());
|
||||
for entry in &table_ref.entries {
|
||||
let state = match &entry.state {
|
||||
ModuleNsState::Value { value, initialized } => ModuleNsState::Value {
|
||||
value: if value.is_object() { rewrite(*value) } else { *value },
|
||||
initialized: *initialized,
|
||||
},
|
||||
ModuleNsState::Cell(cell) => {
|
||||
if !cell.is_null() {
|
||||
// SAFETY: cell 生命周期见 `module_ns_export`;晋升/搬移后改写其内值。
|
||||
let cell_ref = unsafe { &mut **cell };
|
||||
cell_ref.value = rewrite(cell_ref.value);
|
||||
}
|
||||
ModuleNsState::Cell(*cell)
|
||||
}
|
||||
};
|
||||
entries.push(ModuleNsEntry {
|
||||
name_si: entry.name_si,
|
||||
origin: entry.origin,
|
||||
state,
|
||||
});
|
||||
}
|
||||
dst.set_native_data(Box::into_raw(Box::new(ModuleNsTable { entries })) as *mut u8);
|
||||
}
|
||||
|
||||
/// 只读核算条目表的 native 数据字节(不释放),与 `drop_module_ns_native` 的
|
||||
/// capacity 口径一致,供 GC 账目核算。
|
||||
pub fn module_ns_native_size(obj: &JsObject) -> u64 {
|
||||
|
||||
@@ -141,51 +141,6 @@ pub fn set_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
unsafe { (*inner).iter().map(|key| key.0).collect() }
|
||||
}
|
||||
|
||||
/// 克隆 Set 的 native 数据到新对象,用 `rewrite` 改写其中的对象引用。
|
||||
pub fn clone_set_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !src.is_set() {
|
||||
return;
|
||||
}
|
||||
let inner = src.native_data() as *const SetInner;
|
||||
if inner.is_null() {
|
||||
dst.set_native_data(std::ptr::null_mut());
|
||||
return;
|
||||
}
|
||||
let mut cloned = SetInner::new();
|
||||
unsafe {
|
||||
for key in (*inner).iter() {
|
||||
let new_key = if key.0.is_object() { SetKey(rewrite(key.0)) } else { *key };
|
||||
cloned.insert(new_key);
|
||||
}
|
||||
}
|
||||
dst.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
|
||||
}
|
||||
|
||||
/// 原地重写 Set 的 native 数据,用 `rewrite` 改写其中的对象引用。
|
||||
pub fn rewrite_set_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !obj.is_set() {
|
||||
return;
|
||||
}
|
||||
let inner = obj.native_data() as *mut SetInner;
|
||||
if inner.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
let mut rewritten = SetInner::with_capacity((*inner).len());
|
||||
for key in (*inner).iter() {
|
||||
let new_key = if key.0.is_object() { SetKey(rewrite(key.0)) } else { *key };
|
||||
rewritten.insert(new_key);
|
||||
}
|
||||
*inner = rewritten;
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读核算 Set 的 native 数据字节(不释放)。
|
||||
/// 与 `drop_set_native` 释放口径一致(capacity),供 GC 账目核算。
|
||||
pub fn set_native_size(obj: &JsObject) -> u64 {
|
||||
|
||||
@@ -181,39 +181,6 @@ pub fn typed_array_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 克隆 TypedArray 的视图数据到新对象,用 `rewrite` 改写 buffer 引用。
|
||||
pub fn clone_typed_array_native_with_rewrite<F>(old_obj: &JsObject, new_obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
let Some(ptr) = typed_array_data_ptr(old_obj) else {
|
||||
return;
|
||||
};
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
let mut data = unsafe { *ptr };
|
||||
data.buffer = rewrite(data.buffer);
|
||||
let cloned = Box::into_raw(Box::new(data));
|
||||
new_obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(cloned as *const ()) }));
|
||||
}
|
||||
|
||||
/// 原地重写 TypedArray 的 buffer 引用。
|
||||
pub fn rewrite_typed_array_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
let Some(ptr) = typed_array_data_ptr(obj) else {
|
||||
return;
|
||||
};
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
(*ptr).buffer = rewrite((*ptr).buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读核算 TypedArray 视图数据字节(不释放)。
|
||||
pub fn typed_array_native_size(obj: &JsObject) -> u64 {
|
||||
let Some(ptr) = typed_array_data_ptr(obj) else {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
//! WeakMap 条目表:弱键 → 强值。
|
||||
//!
|
||||
//! 键为弱引用(GC mark 不产键边,死键由收集路径按转发表判定后丢条目),
|
||||
//! 值为强引用(值边进 mark 边扫描与晋升改写)。存储盒经 `Box::into_raw` 挂
|
||||
//! `JsObject.native_data`,GC 六站点(mark 边 / 移动式 sweep / 晋升克隆 /
|
||||
//! 原地晋升 / drop / 字节账目)经本模块五函数族接线,口径与 Map/Set 同形。
|
||||
//! 键为弱引用(GC mark 不产键边,死键由原地 sweep 的 mark 位判定后丢条目),
|
||||
//! 值为强引用(值边进 mark 边扫描,原地 sweep 弱键定夺相改写,该相值为恒等
|
||||
//! 改写)。存储盒经 `Box::into_raw` 挂 `JsObject.native_data`,GC 四站点
|
||||
//! (mark 边 / 原地 sweep 弱键定夺 / drop / 字节账目)经本模块四函数族接线,
|
||||
//! 口径与 Map/Set 同形。
|
||||
//! 构造体(iterable 协议)与 set/get/has/delete 四方法的品牌三分枝守卫
|
||||
//! (set/delete 对非 WeakMap this 抛 TypeError,get/has 静默返 undefined/false)
|
||||
//! 也在本模块。
|
||||
@@ -19,7 +20,7 @@ use oxide_types::value::JsValue;
|
||||
/// (interner 保证同符号同 si)。两臂互斥,不可弱持的值不建键。
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum WeakKey {
|
||||
/// 对象键:裸指针仅作哈希键与成员查,生命周期由 GC 转发表判定。
|
||||
/// 对象键:裸指针仅作哈希键与成员查,生命周期由原地 sweep 的 mark 位判定。
|
||||
Obj(*const JsObject),
|
||||
/// symbol 键:interned si 值。
|
||||
Symbol(u32),
|
||||
@@ -120,34 +121,11 @@ pub fn weak_map_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
unsafe { (*inner).entries.values().copied().collect() }
|
||||
}
|
||||
|
||||
/// 克隆 WeakMap 条目表到新对象:键原样搬运(生死判定交晋升后的弱键定夺
|
||||
/// 路径),值经 `rewrite` 改写(强边)。源盒由释放路径单独释放,互不共享。
|
||||
pub fn clone_weak_map_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !src.is_weak_map_obj() {
|
||||
return;
|
||||
}
|
||||
// SAFETY: 源盒指针由构造路径写入,克隆完成 native_data 重指前读取有效。
|
||||
let inner = weak_map_inner_of(src);
|
||||
if inner.is_null() {
|
||||
dst.set_native_data(std::ptr::null_mut());
|
||||
return;
|
||||
}
|
||||
let mut cloned = WeakMapInner::new();
|
||||
unsafe {
|
||||
for (key, value) in (*inner).iter() {
|
||||
let new_value = if value.is_object() { rewrite(value) } else { value };
|
||||
cloned.entries.insert(key, new_value);
|
||||
}
|
||||
}
|
||||
dst.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
|
||||
}
|
||||
|
||||
/// 原地重写 WeakMap 条目表的键与值:键经 `key_resolve` 判定(返回 `None`
|
||||
/// 即死键,条目丢弃;`Some` 改指新键),值经 `value_rewrite` 改写(强边)。
|
||||
/// 按原表整表重建,免条目级原位换键的容量抖动。
|
||||
/// 键不提前改写,键的生死统一由弱键定夺路径判定(原地 sweep 弱键定夺按
|
||||
/// mark 位定生死、死键条目丢弃);提前改写键会引入定夺序依赖。按原表
|
||||
/// 整表重建,免条目级原位换键的容量抖动。
|
||||
pub fn rewrite_weak_map_native<K, V>(obj: &mut JsObject, mut key_resolve: K, mut value_rewrite: V)
|
||||
where
|
||||
K: FnMut(WeakKey) -> Option<WeakKey>,
|
||||
@@ -174,31 +152,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// 原地重写 WeakMap 条目表的值边(强边):键不动,值经 `rewrite` 改写。
|
||||
/// 供晋升主改写路径使用——键的生死须待转发表收敛后由弱键定夺路径判定,
|
||||
/// 本路径提前改写键会引入晋升序依赖。
|
||||
pub fn rewrite_weak_map_native_values<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
if !obj.is_weak_map_obj() {
|
||||
return;
|
||||
}
|
||||
// native_data 同 rewrite_weak_map_native:构造路径写入的有效 Box 指针。
|
||||
let inner = obj.native_data() as *mut WeakMapInner;
|
||||
if inner.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
let mut rewritten = WeakMapInner::with_capacity((*inner).len());
|
||||
for (key, value) in (*inner).iter() {
|
||||
let new_value = if value.is_object() { rewrite(value) } else { value };
|
||||
rewritten.entries.insert(key, new_value);
|
||||
}
|
||||
*inner = rewritten;
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读核算 WeakMap 条目表字节(不释放),供 GC 账目核算;与
|
||||
/// `drop_weak_map_native` 同口径(盒本体 + 桶容量按条目尺寸计)。
|
||||
pub fn weak_map_native_size(obj: &JsObject) -> u64 {
|
||||
|
||||
@@ -78,9 +78,9 @@ pub struct CallFrame {
|
||||
pub continuation: FrameContinuation,
|
||||
/// 被调函数 upvalue cell 表(压帧时从 callee 对象固化,非闭包为 null 空切片)。
|
||||
///
|
||||
/// SAFETY 前提:`callee` 是 GC 根(根遍历/重写/深拷贝三处均遍历该字段),
|
||||
/// 其 `upvalues` Box 创建后不替换(`set_upvalues` 仅 CREATE_CLOSURE 调用一次,
|
||||
/// 晋升克隆共享同一 Box),故指针跨 GC 恒有效;写路径经 `*mut` 转可变切片
|
||||
/// SAFETY 前提:`callee` 是 GC 根(根遍历经该字段),其 `upvalues` Box
|
||||
/// 创建后不替换(`set_upvalues` 仅 CREATE_CLOSURE 调用一次),故指针跨 GC
|
||||
/// 恒有效;写路径经 `*mut` 转可变切片
|
||||
/// 与 `upvalues_slice_mut` 同口径(Box 单所有权)。
|
||||
pub upvalues: *const [*mut Cell],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user