refactor(lifecycle): Phase 285 P2.1 hygiene - lifecycle.rs 箱化完了

責務分離により KeepAlive 処理を handlers/lifecycle.rs に隔離:
- handlers/lifecycle.rs 新規作成(47行)
  - handle_keepalive() で drop_after 判定
  - release_strong_refs() で Arc 同一性探索を集約
  - HashSet による O(1) 検索最適化
- handlers/mod.rs を dispatch 専用化(49行削除→1行呼び出し)
- README.md に P2.1 完了状態を記載(SKIP→PASS)
- phase-29y 将来設計相談パケット追加(NyRT ABI/RC insertion pass)

Test: 154/154 PASS 

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-26 13:36:17 +09:00
parent 3bf0dee2b0
commit f74ff6116c
4 changed files with 254 additions and 67 deletions

View File

@ -0,0 +1,48 @@
use super::*;
use std::collections::HashSet;
use std::sync::Arc;
impl MirInterpreter {
pub(super) fn handle_keepalive(
&mut self,
values: &[ValueId],
drop_after: bool,
) -> Result<(), VMError> {
if drop_after {
self.release_strong_refs(values);
}
Ok(())
}
fn release_strong_refs(&mut self, values: &[ValueId]) {
let mut arc_ptrs: HashSet<*const dyn NyashBox> = HashSet::new();
for value_id in values {
if let Some(VMValue::BoxRef(arc)) = self.regs.get(value_id) {
arc_ptrs.insert(Arc::as_ptr(arc));
}
}
for value_id in values {
self.regs.remove(value_id);
}
if arc_ptrs.is_empty() {
return;
}
let to_remove: Vec<ValueId> = self
.regs
.iter()
.filter_map(|(value_id, value)| match value {
VMValue::BoxRef(arc) if arc_ptrs.contains(&Arc::as_ptr(arc)) => Some(*value_id),
_ => None,
})
.collect();
for value_id in to_remove {
self.regs.remove(&value_id);
}
}
}

View File

@ -21,6 +21,7 @@ mod boxes_void_guards;
mod calls;
mod extern_provider;
mod externals;
mod lifecycle;
mod memory;
mod misc;
mod type_ops;
@ -135,49 +136,7 @@ impl MirInterpreter {
| MirInstruction::Barrier { .. }
| MirInstruction::Safepoint => {}
MirInstruction::KeepAlive { values, drop_after } => {
// Phase 285 P2.1: Handle KeepAlive based on drop_after flag
// - drop_after=true: Release values (for variable overwrite, enables weak ref failure)
// - drop_after=false: Just keep alive (for scope end, values may be needed for PHI)
if *drop_after {
// IMPORTANT: Due to SSA Copy instructions, a single Box may have multiple
// ValueIds pointing to it (e.g., %5 = NewBox, %6 = Copy %5).
// We need to find and remove ALL ValueIds that point to the same Arc.
use std::sync::Arc;
use super::super::vm_types::VMValue;
// Collect raw pointers of Arcs being released
let mut arc_ptrs: Vec<*const dyn crate::box_trait::NyashBox> = Vec::new();
for v in values {
if let Some(VMValue::BoxRef(arc)) = self.regs.get(v) {
arc_ptrs.push(Arc::as_ptr(arc));
}
}
// Remove the specified values first
for v in values {
self.regs.remove(v);
}
// Find and remove ALL other ValueIds that point to the same Arcs
if !arc_ptrs.is_empty() {
let to_remove: Vec<crate::mir::ValueId> = self.regs
.iter()
.filter_map(|(vid, val)| {
if let VMValue::BoxRef(arc) = val {
let ptr = Arc::as_ptr(arc);
if arc_ptrs.contains(&ptr) {
return Some(*vid);
}
}
None
})
.collect();
for vid in to_remove {
self.regs.remove(&vid);
}
}
}
// If drop_after=false, do nothing (values stay alive)
self.handle_keepalive(values, *drop_after)?;
}
MirInstruction::Nop => {}
other => {