mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 11:41:13 +08:00
perf: GC 字节账目补齐 + is_epoch_ptr O(1) + 分配热路径触发
This commit is contained in:
@@ -87,19 +87,33 @@ pub fn clone_array_buffer_native(old_obj: &JsObject, new_obj: &mut JsObject) {
|
||||
new_obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(cloned_ptr as *const ()) }));
|
||||
}
|
||||
|
||||
/// 释放 ArrayBuffer 的字节缓冲(native_fn 槽中的 `Box<Vec<u8>>`),返回字节数。
|
||||
pub fn drop_array_buffer_native(obj: &mut JsObject) -> u64 {
|
||||
/// 只读核算 ArrayBuffer 字节缓冲字节(不释放)。
|
||||
pub fn array_buffer_native_size(obj: &JsObject) -> u64 {
|
||||
let Some(data_ptr) = array_buffer_vec_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
if data_ptr.is_null() {
|
||||
return 0;
|
||||
}
|
||||
// SAFETY: ArrayBuffer 在 native_fn 槽中存 `Box<Vec<u8>>`。
|
||||
unsafe {
|
||||
(std::mem::size_of::<Vec<u8>>() + (*data_ptr).capacity()) as u64
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放 ArrayBuffer 的字节缓冲(native_fn 槽中的 `Box<Vec<u8>>`),返回字节数。
|
||||
pub fn drop_array_buffer_native(obj: &mut JsObject) -> u64 {
|
||||
let bytes = array_buffer_native_size(obj);
|
||||
if bytes == 0 {
|
||||
return 0;
|
||||
}
|
||||
let Some(data_ptr) = array_buffer_vec_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
// SAFETY: data_ptr 非空(array_buffer_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||
let data = unsafe { Box::from_raw(data_ptr) };
|
||||
let bytes = std::mem::size_of::<Vec<u8>>() + data.capacity();
|
||||
drop(data);
|
||||
obj.set_native_fn(None);
|
||||
bytes as u64
|
||||
bytes
|
||||
}
|
||||
|
||||
pub(crate) fn array_buffer_data_ptr<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<*mut Vec<u8>, JsValue> {
|
||||
|
||||
@@ -235,17 +235,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放 DataView 视图数据(`Box<DataViewData>`),返回释放字节数。
|
||||
pub fn drop_data_view_native(obj: &mut JsObject) -> u64 {
|
||||
/// 只读核算 DataView 视图数据字节(不释放)。
|
||||
pub fn data_view_native_size(obj: &JsObject) -> u64 {
|
||||
let Some(ptr) = data_view_data_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
if ptr.is_null() {
|
||||
return 0;
|
||||
}
|
||||
std::mem::size_of::<DataViewData>() as u64
|
||||
}
|
||||
|
||||
/// 释放 DataView 视图数据(`Box<DataViewData>`),返回释放字节数。
|
||||
pub fn drop_data_view_native(obj: &mut JsObject) -> u64 {
|
||||
let bytes = data_view_native_size(obj);
|
||||
if bytes == 0 {
|
||||
return 0;
|
||||
}
|
||||
let Some(ptr) = data_view_data_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
// SAFETY: ptr 非空(data_view_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||
unsafe { drop(Box::from_raw(ptr)) };
|
||||
obj.set_native_fn(None);
|
||||
std::mem::size_of::<DataViewData>() as u64
|
||||
bytes
|
||||
}
|
||||
|
||||
/// `DataView.prototype.getInt8(byteOffset)`:读取 1 字节有符号整数。
|
||||
|
||||
@@ -608,8 +608,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放状态盒(对象被回收时),返回释放的字节数供泄漏统计。
|
||||
pub fn drop_dispose_native(obj: &mut JsObject) -> u64 {
|
||||
/// 只读核算 DisposableStack 状态盒字节(不释放)。
|
||||
pub fn disposable_stack_native_size(obj: &JsObject) -> u64 {
|
||||
if !obj.is_disposable_stack_obj() && !obj.is_async_disposable_stack_obj() {
|
||||
return 0;
|
||||
}
|
||||
@@ -617,13 +617,24 @@ pub fn drop_dispose_native(obj: &mut JsObject) -> u64 {
|
||||
if ptr.is_null() {
|
||||
return 0;
|
||||
}
|
||||
// SAFETY: 指针来自 Box::into_raw,只在对象被回收时释放一次。
|
||||
unsafe {
|
||||
let cap = Box::from_raw(ptr);
|
||||
let bytes =
|
||||
std::mem::size_of::<DisposeCapability>() + cap.entries.capacity() * std::mem::size_of::<DisposeEntry>();
|
||||
drop(cap);
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
bytes as u64
|
||||
(std::mem::size_of::<DisposeCapability>()
|
||||
+ (*ptr).entries.capacity() * std::mem::size_of::<DisposeEntry>()) as u64
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放状态盒(对象被回收时),返回释放的字节数供泄漏统计。
|
||||
pub fn drop_dispose_native(obj: &mut JsObject) -> u64 {
|
||||
let bytes = disposable_stack_native_size(obj);
|
||||
if bytes == 0 {
|
||||
return 0;
|
||||
}
|
||||
let ptr = get_capability_ptr(obj);
|
||||
// SAFETY: ptr 非空(disposable_stack_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||
unsafe {
|
||||
let cap = Box::from_raw(ptr);
|
||||
drop(cap);
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
@@ -132,8 +132,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放 Map 的 native 数据(IndexMap),返回释放的字节数供泄漏统计。
|
||||
pub fn drop_map_native(obj: &mut JsObject) -> u64 {
|
||||
/// 只读核算 Map 的 native 数据字节(不释放)。
|
||||
/// 与 `drop_map_native` 释放口径一致(capacity),供 GC 账目核算。
|
||||
pub fn map_native_size(obj: &JsObject) -> u64 {
|
||||
if !obj.is_map() {
|
||||
return 0;
|
||||
}
|
||||
@@ -142,14 +143,25 @@ pub fn drop_map_native(obj: &mut JsObject) -> u64 {
|
||||
return 0;
|
||||
}
|
||||
unsafe {
|
||||
let boxed: Box<MapInner> = Box::from_raw(inner);
|
||||
let bytes = std::mem::size_of::<MapInner>() + boxed.capacity() * std::mem::size_of::<(SetKey, JsValue)>();
|
||||
drop(boxed);
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
bytes as u64
|
||||
(std::mem::size_of::<MapInner>() + (*inner).capacity() * std::mem::size_of::<(SetKey, JsValue)>()) as u64
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放 Map 的 native 数据(IndexMap),返回释放的字节数供泄漏统计。
|
||||
pub fn drop_map_native(obj: &mut JsObject) -> u64 {
|
||||
let bytes = map_native_size(obj);
|
||||
if bytes == 0 {
|
||||
return 0;
|
||||
}
|
||||
let inner = obj.native_data() as *mut MapInner;
|
||||
// SAFETY: inner 非空(map_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||
unsafe {
|
||||
drop(Box::from_raw(inner));
|
||||
}
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
bytes
|
||||
}
|
||||
|
||||
/// `Map` 构造函数:创建带空 IndexMap native 数据的 Map 对象,若提供可迭代实参
|
||||
/// 则逐元素(须为对象)取 `[0]`/`[1]` 作为键值调用 set。
|
||||
///
|
||||
|
||||
@@ -129,8 +129,8 @@ pub fn regexp_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(obj_ptr))
|
||||
}
|
||||
|
||||
/// 释放 RegExp 对象 native_fn 槽中编译的 `regress::Regex`,返回释放字节数。
|
||||
pub fn drop_regexp_native(obj: &mut JsObject) -> u64 {
|
||||
/// 只读核算 RegExp 编译正则字节(不释放)。
|
||||
pub fn regexp_native_size(obj: &JsObject) -> u64 {
|
||||
if !obj.is_regexp_obj() {
|
||||
return 0;
|
||||
}
|
||||
@@ -141,9 +141,23 @@ pub fn drop_regexp_native(obj: &mut JsObject) -> u64 {
|
||||
if regex_ptr.is_null() {
|
||||
return 0;
|
||||
}
|
||||
std::mem::size_of::<regress::Regex>() as u64
|
||||
}
|
||||
|
||||
/// 释放 RegExp 对象 native_fn 槽中编译的 `regress::Regex`,返回释放字节数。
|
||||
pub fn drop_regexp_native(obj: &mut JsObject) -> u64 {
|
||||
let bytes = regexp_native_size(obj);
|
||||
if bytes == 0 {
|
||||
return 0;
|
||||
}
|
||||
let Some(ptr) = obj.native_fn() else {
|
||||
return 0;
|
||||
};
|
||||
let regex_ptr = ptr.as_ptr() as *mut regress::Regex;
|
||||
// SAFETY: regex_ptr 非空(regexp_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||
unsafe { drop(Box::from_raw(regex_ptr)) };
|
||||
obj.set_native_fn(None);
|
||||
std::mem::size_of::<regress::Regex>() as u64
|
||||
bytes
|
||||
}
|
||||
|
||||
/// 深拷贝已编译正则到新对象(GC 搬移 / 晋升流程用)。
|
||||
|
||||
@@ -173,8 +173,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放 Set 的 native 数据(IndexSet),返回释放的字节数供泄漏统计。
|
||||
pub fn drop_set_native(obj: &mut JsObject) -> u64 {
|
||||
/// 只读核算 Set 的 native 数据字节(不释放)。
|
||||
/// 与 `drop_set_native` 释放口径一致(capacity),供 GC 账目核算。
|
||||
pub fn set_native_size(obj: &JsObject) -> u64 {
|
||||
if !obj.is_set() {
|
||||
return 0;
|
||||
}
|
||||
@@ -183,14 +184,25 @@ pub fn drop_set_native(obj: &mut JsObject) -> u64 {
|
||||
return 0;
|
||||
}
|
||||
unsafe {
|
||||
let boxed: Box<SetInner> = Box::from_raw(inner);
|
||||
let bytes = std::mem::size_of::<SetInner>() + boxed.capacity() * std::mem::size_of::<SetKey>();
|
||||
drop(boxed);
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
bytes as u64
|
||||
(std::mem::size_of::<SetInner>() + (*inner).capacity() * std::mem::size_of::<SetKey>()) as u64
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放 Set 的 native 数据(IndexSet),返回释放的字节数供泄漏统计。
|
||||
pub fn drop_set_native(obj: &mut JsObject) -> u64 {
|
||||
let bytes = set_native_size(obj);
|
||||
if bytes == 0 {
|
||||
return 0;
|
||||
}
|
||||
let inner = obj.native_data() as *mut SetInner;
|
||||
// SAFETY: inner 非空(set_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||
unsafe {
|
||||
drop(Box::from_raw(inner));
|
||||
}
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
bytes
|
||||
}
|
||||
|
||||
/// `Set` 构造函数:创建带空 IndexSet native 数据的 Set 对象,若提供可迭代实参
|
||||
/// 则按插入序逐个 add。
|
||||
///
|
||||
|
||||
@@ -157,17 +157,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放 TypedArray 的视图数据(`Box<TypedArrayData>`),返回释放字节数。
|
||||
pub fn drop_typed_array_native(obj: &mut JsObject) -> u64 {
|
||||
/// 只读核算 TypedArray 视图数据字节(不释放)。
|
||||
pub fn typed_array_native_size(obj: &JsObject) -> u64 {
|
||||
let Some(ptr) = typed_array_data_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
if ptr.is_null() {
|
||||
return 0;
|
||||
}
|
||||
std::mem::size_of::<TypedArrayData>() as u64
|
||||
}
|
||||
|
||||
/// 释放 TypedArray 的视图数据(`Box<TypedArrayData>`),返回释放字节数。
|
||||
pub fn drop_typed_array_native(obj: &mut JsObject) -> u64 {
|
||||
let bytes = typed_array_native_size(obj);
|
||||
if bytes == 0 {
|
||||
return 0;
|
||||
}
|
||||
let Some(ptr) = typed_array_data_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
// SAFETY: ptr 非空(typed_array_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||
unsafe { drop(Box::from_raw(ptr)) };
|
||||
obj.set_native_fn(None);
|
||||
std::mem::size_of::<TypedArrayData>() as u64
|
||||
bytes
|
||||
}
|
||||
|
||||
pub(crate) fn get_typed_array_data<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<TypedArrayData, JsValue> {
|
||||
|
||||
Reference in New Issue
Block a user