mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 03:01:12 +08:00
refactor: Symbol/Iter/Profiling 子结构方法下沉,IC helper 完成提取
This commit is contained in:
@@ -21,6 +21,10 @@ use crate::session_gc::SessionGc;
|
||||
use crate::vm::ForInIter;
|
||||
|
||||
/// Session-arena and garbage-collection bookkeeping.
|
||||
///
|
||||
/// Field-classify only. `mark`/`sweep`/`rewrite_vm_roots` live on `Vm` because
|
||||
/// GC scans all sub-struct roots (regs, frames, for_in_iters, for_of_iters,
|
||||
/// exception_value, etc.) — they cannot be confined to GcState.
|
||||
pub(crate) struct GcState {
|
||||
pub(crate) session_epoch: bumpalo::Bump,
|
||||
pub(crate) session_gc: SessionGc,
|
||||
@@ -28,13 +32,15 @@ pub(crate) struct GcState {
|
||||
pub(crate) session_object_ptrs: Vec<*mut JsObject>,
|
||||
pub(crate) session_string_ptrs: Vec<*mut JsString>,
|
||||
pub(crate) session_bytes_allocated: usize,
|
||||
/// Long-lived forwarding map reused by GC sweep and promote.
|
||||
/// `mem::take`'d out for use, `clear()`'d and put back — capacity retained
|
||||
/// across collections, so no per-event `HashMap` allocation. `FxBuildHasher`
|
||||
/// because the keys are raw pointers (collision resistance is irrelevant).
|
||||
pub(crate) forwarding: HashMap<*mut JsObject, *mut JsObject, FxBuildHasher>,
|
||||
}
|
||||
|
||||
impl GcState {
|
||||
pub(crate) fn track_epoch_object(&mut self, ptr: *mut JsObject) {
|
||||
self.epoch_object_ptrs.push(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/// `Symbol` interning state.
|
||||
pub(crate) struct SymbolState {
|
||||
pub(crate) symbol_counter: u32,
|
||||
@@ -42,6 +48,41 @@ pub(crate) struct SymbolState {
|
||||
pub(crate) symbol_registry: HashMap<String, u32>,
|
||||
}
|
||||
|
||||
impl SymbolState {
|
||||
pub(crate) fn reset(&mut self) {
|
||||
self.symbol_counter = 0;
|
||||
self.symbol_descriptions.clear();
|
||||
self.symbol_registry.clear();
|
||||
}
|
||||
|
||||
pub(crate) fn intern(&mut self, description: String) -> u32 {
|
||||
self.symbol_counter = self.symbol_counter.wrapping_add(1);
|
||||
let idx = self.symbol_descriptions.len() as u32;
|
||||
self.symbol_descriptions.push(description);
|
||||
idx
|
||||
}
|
||||
|
||||
pub(crate) fn register_global(&mut self, key: String, id: u32) {
|
||||
self.symbol_registry.insert(key, id);
|
||||
}
|
||||
|
||||
pub(crate) fn lookup_global(&self, key: &str) -> Option<u32> {
|
||||
self.symbol_registry.get(key).copied()
|
||||
}
|
||||
|
||||
pub(crate) fn description(&self, id: u32) -> Option<&str> {
|
||||
self.symbol_descriptions.get(id as usize).map(|s| s.as_str())
|
||||
}
|
||||
|
||||
pub(crate) fn key_for_id(&self, id: u32) -> Option<String> {
|
||||
self.symbol_registry.iter().find(|(_, &v)| v == id).map(|(k, _)| k.clone())
|
||||
}
|
||||
|
||||
pub(crate) fn registry_len(&self) -> usize {
|
||||
self.symbol_registry.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// Live iterator state for `for-in` / `for-of`.
|
||||
pub(crate) struct IterState {
|
||||
pub(crate) for_in_iters: Vec<*mut ForInIter<'static>>,
|
||||
@@ -49,9 +90,76 @@ pub(crate) struct IterState {
|
||||
pub(crate) last_for_of_result: JsValue,
|
||||
}
|
||||
|
||||
impl IterState {
|
||||
pub(crate) fn reset(&mut self) {
|
||||
self.for_in_iters.clear();
|
||||
self.for_of_iters.clear();
|
||||
self.last_for_of_result = JsValue::undefined();
|
||||
}
|
||||
|
||||
pub(crate) fn push_for_in(&mut self, iter: *mut ForInIter<'static>) {
|
||||
self.for_in_iters.push(iter);
|
||||
}
|
||||
|
||||
pub(crate) fn pop_for_in(&mut self) {
|
||||
self.for_in_iters.pop();
|
||||
}
|
||||
|
||||
pub(crate) fn last_for_in(&self) -> *mut ForInIter<'static> {
|
||||
self.for_in_iters.last().copied().unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
pub(crate) fn push_for_of(&mut self, val: JsValue) {
|
||||
self.for_of_iters.push(val);
|
||||
}
|
||||
|
||||
pub(crate) fn last_for_of(&self) -> Option<JsValue> {
|
||||
self.for_of_iters.last().copied()
|
||||
}
|
||||
|
||||
pub(crate) fn pop_for_of(&mut self) -> Option<JsValue> {
|
||||
self.for_of_iters.pop()
|
||||
}
|
||||
|
||||
pub(crate) fn last_for_of_result(&self) -> JsValue {
|
||||
self.last_for_of_result
|
||||
}
|
||||
|
||||
pub(crate) fn set_last_for_of_result(&mut self, val: JsValue) {
|
||||
self.last_for_of_result = val;
|
||||
}
|
||||
|
||||
pub(crate) fn clear_last_for_of_result(&mut self) {
|
||||
self.last_for_of_result = JsValue::undefined();
|
||||
}
|
||||
}
|
||||
|
||||
/// Inline-cache hit/miss and instruction counters.
|
||||
pub(crate) struct ProfilingState {
|
||||
pub(crate) ic_hits: Cell<u64>,
|
||||
pub(crate) ic_misses: Cell<u64>,
|
||||
pub(crate) instruction_count: u64,
|
||||
}
|
||||
|
||||
impl ProfilingState {
|
||||
pub(crate) fn record_ic_hit(&self) {
|
||||
self.ic_hits.set(self.ic_hits.get() + 1);
|
||||
}
|
||||
|
||||
pub(crate) fn record_ic_miss(&self) {
|
||||
self.ic_misses.set(self.ic_misses.get() + 1);
|
||||
}
|
||||
|
||||
pub(crate) fn set_instruction_count(&mut self, count: u64) {
|
||||
self.instruction_count = count;
|
||||
}
|
||||
|
||||
pub(crate) fn ic_hit_rate(&self) -> f64 {
|
||||
let total = self.ic_hits.get() + self.ic_misses.get();
|
||||
if total == 0 {
|
||||
0.0
|
||||
} else {
|
||||
self.ic_hits.get() as f64 / total as f64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user