Files
hakorune/src/scope_tracker.rs
Moe Charm 53d88157aa Phase 12: 統一TypeBox ABI実装開始 - ChatGPT5による極小コアABI基盤構築
- TypeBox ABI雛形: メソッドスロット管理システム追加
- Type Registry: Array/Map/StringBoxの基本メソッド定義
- Host API: C ABI逆呼び出しシステム実装
- Phase 12ドキュメント整理: 設計文書統合・アーカイブ化
- MIR Builder: クリーンアップと分離実装完了

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 05:04:56 +09:00

131 lines
4.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* ScopeTracker - Track Box instances for proper lifecycle management
*
* Phase 9.78a: Unified Box lifecycle management for VM
*/
use std::sync::Arc;
use crate::box_trait::NyashBox;
use crate::instance_v2::InstanceBox;
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
use crate::runtime::plugin_loader_v2::PluginBoxV2;
/// Tracks Box instances created in different scopes for proper fini calls
pub struct ScopeTracker {
/// Stack of scopes, each containing Boxes created in that scope
scopes: Vec<Vec<Arc<dyn NyashBox>>>,
/// Root regions for GC (values pinned as roots during a dynamic region)
roots: Vec<Vec<crate::backend::vm::VMValue>>,
}
impl ScopeTracker {
/// Create a new scope tracker
pub fn new() -> Self {
Self {
scopes: vec![Vec::new()], // Start with one root scope
roots: vec![Vec::new()], // Start with one root region
}
}
/// Enter a new scope
pub fn push_scope(&mut self) {
self.scopes.push(Vec::new());
}
/// Exit current scope and call fini on all Boxes created in it
pub fn pop_scope(&mut self) {
if let Some(scope) = self.scopes.pop() {
// Call fini in reverse order of creation
for arc_box in scope.into_iter().rev() {
// InstanceBox: call fini()
if let Some(instance) = arc_box.as_any().downcast_ref::<InstanceBox>() {
let _ = instance.fini();
continue;
}
// PluginBoxV2: 明示ライフサイクルに合わせ、スコープ終了時にfini自己責任運用
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
if let Some(p) = arc_box.as_any().downcast_ref::<PluginBoxV2>() {
p.finalize_now();
continue;
}
// Builtin and others: no-op for now
}
}
// Ensure we always have at least one scope
if self.scopes.is_empty() { self.scopes.push(Vec::new()); }
}
/// Register a Box in the current scope
pub fn register_box(&mut self, nyash_box: Arc<dyn NyashBox>) {
if let Some(current_scope) = self.scopes.last_mut() {
current_scope.push(nyash_box);
}
}
/// Clear all scopes (used when resetting VM state)
pub fn clear(&mut self) {
// Pop all scopes and call fini
while self.scopes.len() > 1 {
self.pop_scope();
}
// Clear the root scope
if let Some(root_scope) = self.scopes.first_mut() {
root_scope.clear();
}
// Reset roots to a single empty region
self.roots.clear();
self.roots.push(Vec::new());
}
// ===== GC root region API (Phase 10.4 prep) =====
/// Enter a new GC root region
pub fn enter_root_region(&mut self) {
if crate::config::env::gc_trace() {
eprintln!("[GC] roots: enter");
}
self.roots.push(Vec::new());
}
/// Leave current GC root region (dropping all pinned values)
pub fn leave_root_region(&mut self) {
if let Some(_) = self.roots.pop() {
if crate::config::env::gc_trace() {
eprintln!("[GC] roots: leave");
}
}
if self.roots.is_empty() { self.roots.push(Vec::new()); }
}
/// Pin a VMValue into the current root region (cheap clone)
pub fn pin_root(&mut self, v: &crate::backend::vm::VMValue) {
if let Some(cur) = self.roots.last_mut() {
cur.push(v.clone());
if crate::config::env::gc_trace() {
eprintln!("[GC] roots: pin {:?}", v);
}
}
}
/// Total number of pinned roots across all regions (for GC PoC diagnostics)
pub fn root_count_total(&self) -> usize { self.roots.iter().map(|r| r.len()).sum() }
/// Number of active root regions
pub fn root_regions(&self) -> usize { self.roots.len() }
/// Snapshot a flat vector of current roots (cloned) for diagnostics
pub fn roots_snapshot(&self) -> Vec<crate::backend::vm::VMValue> {
let mut out = Vec::new();
for region in &self.roots { out.extend(region.iter().cloned()); }
out
}
}
impl Default for ScopeTracker {
fn default() -> Self {
Self::new()
}
}