mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 19:21:11 +08:00
refactor: realm 与 Vm 生命周期解耦,Vm 持 Arc<Realm>
This commit is contained in:
@@ -50,7 +50,7 @@ impl SessionGc {
|
||||
/// 清空 session 对象表的 GC mark 位。置位不随表清位消失,残留位会让下一次
|
||||
/// `mark` 的 DFS 在已标对象处短路,漏扫其新增引用边。
|
||||
pub(crate) fn clear_all_marks(&mut self, vm: &mut Vm) {
|
||||
vm_debug!("[GC] clear_all_marks: {} session objects", vm.realm.gc.session_object_ptrs.len());
|
||||
vm_debug!("[GC] clear_all_marks: {} session objects", vm.realm.gc.borrow().session_object_ptrs.len());
|
||||
self.clear_session_marks(vm);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ impl SessionGc {
|
||||
/// 与收集前历史残留——残留 true 会让下一次 `mark` 的 DFS 在已标对象处
|
||||
/// 短路,漏扫其新增引用边。
|
||||
pub(crate) fn clear_session_marks(&mut self, vm: &mut Vm) {
|
||||
for &ptr in &vm.realm.gc.session_object_ptrs {
|
||||
for &ptr in &vm.realm.gc.borrow().session_object_ptrs {
|
||||
if ptr.is_null() {
|
||||
continue;
|
||||
}
|
||||
@@ -650,7 +650,7 @@ impl SessionGc {
|
||||
/// `sweep`(完整收集)与 `collect_in_run`(执行期收集)共用,保证两条
|
||||
/// 收集路径的弱键定夺口径一致。返回 (存活数, 死数, 释放字节)。
|
||||
fn sweep_in_place(&mut self, vm: &mut Vm) -> (u64, u64, u64) {
|
||||
let old_ptrs = std::mem::take(&mut vm.realm.gc.session_object_ptrs);
|
||||
let old_ptrs = std::mem::take(&mut vm.realm.gc.borrow_mut().session_object_ptrs);
|
||||
let mut survivors = Vec::with_capacity(old_ptrs.len());
|
||||
|
||||
// 弱键定夺先于死对象释放:键对象(含死键)此刻全部仍分配,
|
||||
@@ -689,12 +689,15 @@ impl SessionGc {
|
||||
}
|
||||
}
|
||||
let live = survivors.len() as u64;
|
||||
vm.realm.gc.session_object_ptrs = survivors;
|
||||
vm.realm.gc.borrow_mut().session_object_ptrs = survivors;
|
||||
|
||||
// 对象口径重算:存活对象头 + 堆数据求和(串/BigInt/cell 分量不在此口径,
|
||||
// 由各清扫路径按存活补回,与完整收集的最终账目一致)。
|
||||
vm.realm.gc.session_bytes_allocated = vm
|
||||
.realm.gc
|
||||
// 由各清扫路径按存活补回,与完整收集的最终账目一致)。读入局部变量后
|
||||
// 释放借用再写回,不跨读写持借。
|
||||
let new_bytes: usize = vm
|
||||
.realm
|
||||
.gc
|
||||
.borrow()
|
||||
.session_object_ptrs
|
||||
.iter()
|
||||
.filter(|&&ptr| !ptr.is_null())
|
||||
@@ -704,6 +707,7 @@ impl SessionGc {
|
||||
size_of::<JsObject>() as u64 + Self::object_heap_data_bytes(obj)
|
||||
})
|
||||
.sum::<u64>() as usize;
|
||||
vm.realm.gc.borrow_mut().session_bytes_allocated = new_bytes;
|
||||
|
||||
// 统计按对象口径累计(串/BigInt/cell 清扫在其上累加释放字节)。
|
||||
self.total_bytes_freed = self.total_bytes_freed.saturating_add(freed_bytes);
|
||||
@@ -737,8 +741,8 @@ impl SessionGc {
|
||||
/// `session_bytes_allocated` 重置为仅对象),再补回存活字符串字节。
|
||||
/// 返回释放的字节数。
|
||||
pub(crate) fn sweep_session_strings(&mut self, vm: &mut Vm) -> u64 {
|
||||
vm_debug!("[GC] sweep strings: {} string ptrs", vm.realm.gc.session_string_ptrs.len());
|
||||
let old = std::mem::take(&mut vm.realm.gc.session_string_ptrs);
|
||||
vm_debug!("[GC] sweep strings: {} string ptrs", vm.realm.gc.borrow().session_string_ptrs.len());
|
||||
let old = std::mem::take(&mut vm.realm.gc.borrow_mut().session_string_ptrs);
|
||||
let mut freed = 0u64;
|
||||
let mut live_bytes = 0usize;
|
||||
let mut live = Vec::with_capacity(old.len());
|
||||
@@ -756,8 +760,9 @@ impl SessionGc {
|
||||
freed += unsafe { Self::drop_dead_session_string(ptr) };
|
||||
}
|
||||
}
|
||||
vm.realm.gc.session_string_ptrs = live;
|
||||
vm.realm.gc.session_bytes_allocated = vm.realm.gc.session_bytes_allocated.saturating_add(live_bytes);
|
||||
vm.realm.gc.borrow_mut().session_string_ptrs = live;
|
||||
let new_bytes = vm.realm.gc.borrow().session_bytes_allocated.saturating_add(live_bytes);
|
||||
vm.realm.gc.borrow_mut().session_bytes_allocated = new_bytes;
|
||||
|
||||
self.total_bytes_freed = self.total_bytes_freed.saturating_add(freed);
|
||||
self.last_collection_bytes_freed = self.last_collection_bytes_freed.saturating_add(freed);
|
||||
@@ -769,7 +774,7 @@ impl SessionGc {
|
||||
/// forwarding 表与根指针重写。在字符串清扫之后运行。
|
||||
/// 返回释放的字节数。
|
||||
pub(crate) fn sweep_session_bigints(&mut self, vm: &mut Vm) -> u64 {
|
||||
let old = vm.realm.gc.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 {
|
||||
@@ -788,7 +793,7 @@ impl SessionGc {
|
||||
}
|
||||
}
|
||||
}
|
||||
*vm.realm.gc.session_bigint_ptrs.borrow_mut() = live;
|
||||
*vm.realm.gc.borrow_mut().session_bigint_ptrs.borrow_mut() = live;
|
||||
|
||||
self.total_bytes_freed = self.total_bytes_freed.saturating_add(freed);
|
||||
self.last_collection_bytes_freed = self.last_collection_bytes_freed.saturating_add(freed);
|
||||
@@ -804,7 +809,7 @@ impl SessionGc {
|
||||
/// 统计、不重算存活账目。
|
||||
/// 返回释放的字节数。
|
||||
pub(crate) fn sweep_session_cells(&mut self, vm: &mut Vm) -> u64 {
|
||||
let old = vm.realm.gc.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 {
|
||||
@@ -822,7 +827,7 @@ impl SessionGc {
|
||||
}
|
||||
}
|
||||
}
|
||||
*vm.realm.gc.session_cell_ptrs.borrow_mut() = live;
|
||||
*vm.realm.gc.borrow_mut().session_cell_ptrs.borrow_mut() = live;
|
||||
|
||||
self.total_bytes_freed = self.total_bytes_freed.saturating_add(freed);
|
||||
self.last_collection_bytes_freed = self.last_collection_bytes_freed.saturating_add(freed);
|
||||
@@ -831,10 +836,11 @@ impl SessionGc {
|
||||
|
||||
/// 完整收集的触发判断:对象、字符串或 BigInt 表非空,且字节账目已达阈值。
|
||||
pub(crate) fn should_collect(&self, vm: &Vm) -> bool {
|
||||
(!vm.realm.gc.session_object_ptrs.is_empty()
|
||||
|| !vm.realm.gc.session_string_ptrs.is_empty()
|
||||
|| !vm.realm.gc.session_bigint_ptrs.borrow().is_empty())
|
||||
&& vm.realm.gc.session_bytes_allocated >= vm.kernel_core().config().session_gc_threshold
|
||||
let gc = vm.realm.gc.borrow();
|
||||
(!gc.session_object_ptrs.is_empty()
|
||||
|| !gc.session_string_ptrs.is_empty()
|
||||
|| !gc.session_bigint_ptrs.borrow().is_empty())
|
||||
&& gc.session_bytes_allocated >= vm.kernel_core().config().session_gc_threshold
|
||||
}
|
||||
|
||||
/// 执行期字符串回收的触发判断:账目须超过水位(上次收集后的存活字节 +
|
||||
@@ -842,10 +848,11 @@ impl SessionGc {
|
||||
/// 保证死对象超阈值即被 reset 回收;执行期走增量水位,活串超阈值时不每指令
|
||||
/// 重复触发无死串可回收的白跑。
|
||||
pub(crate) fn should_collect_strings(&self, vm: &Vm) -> bool {
|
||||
(!vm.realm.gc.session_object_ptrs.is_empty()
|
||||
|| !vm.realm.gc.session_string_ptrs.is_empty()
|
||||
|| !vm.realm.gc.session_bigint_ptrs.borrow().is_empty())
|
||||
&& vm.realm.gc.session_bytes_allocated >= vm.realm.gc.string_gc_watermark
|
||||
let gc = vm.realm.gc.borrow();
|
||||
(!gc.session_object_ptrs.is_empty()
|
||||
|| !gc.session_string_ptrs.is_empty()
|
||||
|| !gc.session_bigint_ptrs.borrow().is_empty())
|
||||
&& gc.session_bytes_allocated >= gc.string_gc_watermark
|
||||
}
|
||||
|
||||
/// debug 兜底:mark 之后断言所有存活对象持有的字符串边都已登记进
|
||||
@@ -853,7 +860,7 @@ impl SessionGc {
|
||||
#[cfg(debug_assertions)]
|
||||
fn debug_assert_marked_object_strings_live(&self, vm: &Vm) {
|
||||
let mut live = HashSet::with_hasher(FxBuildHasher);
|
||||
for &ptr in &vm.realm.gc.session_object_ptrs {
|
||||
for &ptr in &vm.realm.gc.borrow().session_object_ptrs {
|
||||
if ptr.is_null() {
|
||||
continue;
|
||||
}
|
||||
@@ -942,7 +949,9 @@ impl SessionGc {
|
||||
|
||||
// 扣减字符串账目(保留对象账目),再补回存活串字节。
|
||||
let object_bytes: usize = vm
|
||||
.realm.gc
|
||||
.realm
|
||||
.gc
|
||||
.borrow()
|
||||
.session_object_ptrs
|
||||
.iter()
|
||||
.filter(|&&ptr| !ptr.is_null())
|
||||
@@ -951,7 +960,7 @@ impl SessionGc {
|
||||
size_of::<JsObject>() as u64 + Self::object_heap_data_bytes(obj)
|
||||
})
|
||||
.sum::<u64>() as usize;
|
||||
vm.realm.gc.session_bytes_allocated = object_bytes;
|
||||
vm.realm.gc.borrow_mut().session_bytes_allocated = object_bytes;
|
||||
let mut freed_bytes = self.sweep_session_strings(vm);
|
||||
freed_bytes += self.sweep_session_bigints(vm);
|
||||
freed_bytes += self.sweep_session_cells(vm);
|
||||
@@ -962,9 +971,10 @@ impl SessionGc {
|
||||
self.clear_all_marks(vm);
|
||||
|
||||
// 抬高下次触发水位:本次存活字节 + 阈值增量,避免活串超阈值时每指令重复
|
||||
// 触发无死串可回收的完整 mark + 串清扫。
|
||||
// 触发无死串可回收的完整 mark + 串清扫。读入局部变量后释放借用再写回。
|
||||
let threshold = vm.kernel_core().config().session_gc_threshold;
|
||||
vm.realm.gc.string_gc_watermark = vm.realm.gc.session_bytes_allocated.saturating_add(threshold);
|
||||
let new_watermark = vm.realm.gc.borrow().session_bytes_allocated.saturating_add(threshold);
|
||||
vm.realm.gc.borrow_mut().string_gc_watermark = new_watermark;
|
||||
|
||||
let elapsed = start.elapsed();
|
||||
self.total_collections += 1;
|
||||
@@ -1034,18 +1044,21 @@ impl SessionGc {
|
||||
// 串,串表整体计入,与 strings-only 口径一致;BigInt/cell 不在手工
|
||||
// 账目内,由 `run_alloc_bytes` 公式按表长单列)。
|
||||
let mut string_bytes: usize = 0;
|
||||
for &ptr in &vm.realm.gc.session_string_ptrs {
|
||||
for &ptr in &vm.realm.gc.borrow().session_string_ptrs {
|
||||
if ptr.is_null() {
|
||||
continue;
|
||||
}
|
||||
// SAFETY: ptr 在字符串表登记,收尾前有效。
|
||||
string_bytes += size_of::<JsString>() + unsafe { (*ptr).payload_bytes() };
|
||||
}
|
||||
vm.realm.gc.session_bytes_allocated = vm.realm.gc.session_bytes_allocated.saturating_add(string_bytes);
|
||||
let new_bytes = vm.realm.gc.borrow().session_bytes_allocated.saturating_add(string_bytes);
|
||||
vm.realm.gc.borrow_mut().session_bytes_allocated = new_bytes;
|
||||
|
||||
// 抬高下次触发水位:当前分配包络 + 阈值增量——存活包络超阈值时不每指令
|
||||
// 重复触发无死对象可回收的白跑。
|
||||
vm.realm.gc.gc_watermark = vm.run_alloc_bytes().saturating_add(vm.realm.gc.gc_threshold_cached);
|
||||
// 重复触发无死对象可回收的白跑。读入局部变量后释放借用再写回。
|
||||
let alloc = vm.run_alloc_bytes();
|
||||
let threshold = vm.realm.gc.borrow().gc_threshold_cached;
|
||||
vm.realm.gc.borrow_mut().gc_watermark = alloc.saturating_add(threshold);
|
||||
|
||||
let elapsed = start.elapsed();
|
||||
self.total_collections += 1;
|
||||
|
||||
Reference in New Issue
Block a user