Phase 287: KeepAlive/ReleaseStrong 命令分離
## 変更内容(2つの側面)
### 1. 命令セマンティクスの分離
- KeepAlive { values, drop_after: bool } を2命令に分離
- KeepAlive { values }: スコープ終了での生存維持(PURE)
- ReleaseStrong { values }: 変数上書き時の強参照解放(WRITE)
- 効果分析の明確化: PURE vs WRITE の境界確定
### 2. VM実行サポート
- handlers/mod.rs: KeepAlive → 完全 no-op
- handlers/mod.rs: ReleaseStrong → release_strong_refs() 呼び出し
- handlers/lifecycle.rs: handle_keepalive() 削除
## 影響範囲
- 10 ファイル修正(31箇所の出現を全変換)
- instruction.rs, builder.rs, lexical_scope.rs, methods.rs,
display.rs, printer_helpers.rs, query.rs, joinir_id_remapper.rs,
handlers/mod.rs, handlers/lifecycle.rs
## 検証
- 154/154 quick smoke PASS
- weak テスト回帰なし(weak_upgrade_fail, weak_basic)
- rg -n drop_after src → 0 件(完全除去確認)
- MIRダンプで release_strong/keepalive 正常表示
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
177 lines
6.4 KiB
Rust
177 lines
6.4 KiB
Rust
//! MirQuery - Read/Write/CFGビューを提供する共通窓口
|
||
//!
|
||
//! Box理論: MIR 全体の構造は MirQueryBox が保持し、他の箱(ExitLiveness など)は
|
||
//! 「見せる窓」である MirQuery トレイト越しにしか触らないようにする。
|
||
//! これにより MIR 構造への依存を最小化し、テスタビリティと疎結合を保つ。
|
||
|
||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||
|
||
/// MIR への読み取り専用ビュー
|
||
pub trait MirQuery {
|
||
/// ブロック内の命令列(PHI を含む)を順序付きで返す
|
||
fn insts_in_block(&self, bb: BasicBlockId) -> &[MirInstruction];
|
||
|
||
/// ブロックの後続(succs)を決定的順序で返す
|
||
fn succs(&self, bb: BasicBlockId) -> Vec<BasicBlockId>;
|
||
|
||
/// 命令が読む(use する)ValueId のリスト
|
||
fn reads_of(&self, inst: &MirInstruction) -> Vec<ValueId>;
|
||
|
||
/// 命令が書く(def する)ValueId のリスト
|
||
fn writes_of(&self, inst: &MirInstruction) -> Vec<ValueId>;
|
||
}
|
||
|
||
/// MirQuery の標準実装:MirFunction 全体を抱えつつビューを提供
|
||
pub struct MirQueryBox<'m> {
|
||
mir: &'m MirFunction,
|
||
}
|
||
|
||
impl<'m> MirQueryBox<'m> {
|
||
pub fn new(mir: &'m MirFunction) -> Self {
|
||
Self { mir }
|
||
}
|
||
}
|
||
|
||
impl<'m> MirQuery for MirQueryBox<'m> {
|
||
fn insts_in_block(&self, bb: BasicBlockId) -> &[MirInstruction] {
|
||
static EMPTY: &[MirInstruction] = &[];
|
||
self.mir
|
||
.blocks
|
||
.get(&bb)
|
||
.map(|bb| bb.instructions.as_slice())
|
||
.unwrap_or(EMPTY)
|
||
}
|
||
|
||
fn succs(&self, bb: BasicBlockId) -> Vec<BasicBlockId> {
|
||
let mut v: Vec<_> = self
|
||
.mir
|
||
.blocks
|
||
.get(&bb)
|
||
.map(|bb| bb.successors.iter().copied().collect())
|
||
.unwrap_or_else(Vec::new);
|
||
v.sort_by_key(|b| b.0);
|
||
v
|
||
}
|
||
|
||
fn reads_of(&self, inst: &MirInstruction) -> Vec<ValueId> {
|
||
use MirInstruction::*;
|
||
match inst {
|
||
Const { .. } | Nop => Vec::new(),
|
||
Copy { src, .. } => vec![*src],
|
||
UnaryOp { operand, .. } => vec![*operand],
|
||
BinOp { lhs, rhs, .. } | Compare { lhs, rhs, .. } => {
|
||
vec![*lhs, *rhs]
|
||
}
|
||
TypeOp { value, .. } | TypeCheck { value, .. } | Cast { value, .. } => {
|
||
vec![*value]
|
||
}
|
||
Load { ptr, .. } => vec![*ptr],
|
||
Store { ptr, value } => vec![*ptr, *value],
|
||
ArrayGet { array, index, .. } => vec![*array, *index],
|
||
ArraySet {
|
||
array,
|
||
index,
|
||
value,
|
||
..
|
||
} => vec![*array, *index, *value],
|
||
Call { args, .. }
|
||
| BoxCall { args, .. }
|
||
| PluginInvoke { args, .. }
|
||
| ExternCall { args, .. } => args.clone(),
|
||
Return { value } => value.iter().copied().collect(),
|
||
Branch { condition, .. } => vec![*condition],
|
||
Jump { .. } => Vec::new(),
|
||
Phi { inputs, .. } => inputs.iter().map(|(_, v)| *v).collect(),
|
||
NewBox { args, .. } => args.clone(),
|
||
Debug { value, .. } | Print { value, .. } => vec![*value],
|
||
DebugLog { values, .. } => values.clone(),
|
||
// Phase 287: Lifecycle management reads all values
|
||
KeepAlive { values } => values.clone(),
|
||
ReleaseStrong { values } => values.clone(),
|
||
Throw { exception, .. } => vec![*exception],
|
||
Catch { .. } => Vec::new(),
|
||
NewClosure { captures, me, .. } => {
|
||
let mut v: Vec<ValueId> = captures.iter().map(|(_, v)| *v).collect();
|
||
if let Some(m) = me {
|
||
v.push(*m);
|
||
}
|
||
v
|
||
}
|
||
RefNew { box_val, .. } => vec![*box_val],
|
||
RefGet { reference, .. } => vec![*reference],
|
||
RefSet {
|
||
reference, value, ..
|
||
} => vec![*reference, *value],
|
||
WeakNew { box_val, .. } => vec![*box_val],
|
||
WeakLoad { weak_ref, .. } => vec![*weak_ref],
|
||
WeakRef { value, .. } => vec![*value],
|
||
BarrierRead { ptr } | BarrierWrite { ptr } | Barrier { ptr, .. } => {
|
||
vec![*ptr]
|
||
}
|
||
FutureNew { value, .. } => vec![*value],
|
||
FutureSet { future, value } => vec![*future, *value],
|
||
Await { future, .. } => vec![*future],
|
||
Safepoint => Vec::new(),
|
||
// Phase 256 P1.5: Select instruction reads cond, then_val, else_val
|
||
Select {
|
||
cond,
|
||
then_val,
|
||
else_val,
|
||
..
|
||
} => vec![*cond, *then_val, *else_val],
|
||
}
|
||
}
|
||
|
||
fn writes_of(&self, inst: &MirInstruction) -> Vec<ValueId> {
|
||
use MirInstruction::*;
|
||
match inst {
|
||
Const { dst, .. }
|
||
| UnaryOp { dst, .. }
|
||
| BinOp { dst, .. }
|
||
| Compare { dst, .. }
|
||
| TypeOp { dst, .. }
|
||
| Cast { dst, .. }
|
||
| Load { dst, .. }
|
||
| ArrayGet { dst, .. }
|
||
| Call { dst: Some(dst), .. }
|
||
| BoxCall { dst: Some(dst), .. }
|
||
| PluginInvoke { dst: Some(dst), .. }
|
||
| ExternCall { dst: Some(dst), .. }
|
||
| Phi { dst, .. }
|
||
| NewBox { dst, .. }
|
||
| RefNew { dst, .. }
|
||
| RefGet { dst, .. }
|
||
| WeakNew { dst, .. }
|
||
| WeakLoad { dst, .. }
|
||
| WeakRef { dst, .. }
|
||
| FutureNew { dst, .. }
|
||
| NewClosure { dst, .. }
|
||
| Await { dst, .. }
|
||
| Copy { dst, .. }
|
||
| Select { dst, .. } => vec![*dst], // Copy writes to dst, Select writes to dst
|
||
// No writes
|
||
Nop
|
||
| Store { .. }
|
||
| ArraySet { .. }
|
||
| Call { dst: None, .. }
|
||
| BoxCall { dst: None, .. }
|
||
| PluginInvoke { dst: None, .. }
|
||
| ExternCall { dst: None, .. }
|
||
| Return { .. }
|
||
| Branch { .. }
|
||
| Jump { .. }
|
||
| Debug { .. }
|
||
| DebugLog { .. }
|
||
| Print { .. }
|
||
| Throw { .. }
|
||
| Catch { .. }
|
||
| BarrierRead { .. }
|
||
| BarrierWrite { .. }
|
||
| Barrier { .. }
|
||
| FutureSet { .. }
|
||
| Safepoint => Vec::new(),
|
||
_ => Vec::new(),
|
||
}
|
||
}
|
||
}
|