refactor(vm): Phase 8 - Debug Trace Macro統一化(12行削減)

trace_dispatch!マクロで6箇所のVM_TRACEパターンを統一

実装内容:
- mod.rsにtrace_dispatch!マクロ定義
- boxes.rs: 6箇所の3行if文→1行マクロ呼び出し
- 削減: 18行→6行(12行削減)

対象箇所:
- object_fields handler trace
- instance_box handler trace
- string_box handler trace
- array_box handler trace
- map_box handler trace
- fallback(length=0) handler trace

効果:
- 保守性向上: trace条件の一元管理
- 可読性向上: 冗長なif文→簡潔なマクロ
- 一貫性向上: 全handler統一フォーマット

テスト: ビルド成功(0エラー、87警告)
This commit is contained in:
nyash-codex
2025-11-01 13:46:34 +09:00
parent 9be50f0a0c
commit 167d33ed9e
5 changed files with 124 additions and 82 deletions

View File

@ -168,9 +168,7 @@ impl MirInterpreter {
_ => {} _ => {}
} }
if super::boxes_object_fields::try_handle_object_fields(self, dst, box_val, method, args)? { if super::boxes_object_fields::try_handle_object_fields(self, dst, box_val, method, args)? {
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") { trace_dispatch!(method, "object_fields");
eprintln!("[vm-trace] length dispatch handler=object_fields");
}
return Ok(()); return Ok(());
} }
// Policy gate: user InstanceBox BoxCall runtime fallback // Policy gate: user InstanceBox BoxCall runtime fallback
@ -201,36 +199,26 @@ impl MirInterpreter {
} }
} }
if super::boxes_instance::try_handle_instance_box(self, dst, box_val, method, args)? { if super::boxes_instance::try_handle_instance_box(self, dst, box_val, method, args)? {
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") { trace_dispatch!(method, "instance_box");
eprintln!("[vm-trace] length dispatch handler=instance_box");
}
return Ok(()); return Ok(());
} }
if super::boxes_string::try_handle_string_box(self, dst, box_val, method, args)? { if super::boxes_string::try_handle_string_box(self, dst, box_val, method, args)? {
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") { trace_dispatch!(method, "string_box");
eprintln!("[vm-trace] length dispatch handler=string_box");
}
return Ok(()); return Ok(());
} }
if super::boxes_array::try_handle_array_box(self, dst, box_val, method, args)? { if super::boxes_array::try_handle_array_box(self, dst, box_val, method, args)? {
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") { trace_dispatch!(method, "array_box");
eprintln!("[vm-trace] length dispatch handler=array_box");
}
return Ok(()); return Ok(());
} }
if super::boxes_map::try_handle_map_box(self, dst, box_val, method, args)? { if super::boxes_map::try_handle_map_box(self, dst, box_val, method, args)? {
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") { trace_dispatch!(method, "map_box");
eprintln!("[vm-trace] length dispatch handler=map_box");
}
return Ok(()); return Ok(());
} }
// Narrow safety valve: if 'length' wasn't handled by any box-specific path, // Narrow safety valve: if 'length' wasn't handled by any box-specific path,
// treat it as 0 (avoids Lt on Void in common loops). This is a dev-time // treat it as 0 (avoids Lt on Void in common loops). This is a dev-time
// robustness measure; precise behavior should be provided by concrete boxes. // robustness measure; precise behavior should be provided by concrete boxes.
if method == "length" { if method == "length" {
if std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") { trace_dispatch!(method, "fallback(length=0)");
eprintln!("[vm-trace] length dispatch handler=fallback(length=0)");
}
if let Some(d) = dst { self.regs.insert(d, VMValue::Integer(0)); } if let Some(d) = dst { self.regs.insert(d, VMValue::Integer(0)); }
return Ok(()); return Ok(());
} }

View File

@ -1,5 +1,16 @@
use super::*; use super::*;
// VM dispatch trace macro (used across handlers)
macro_rules! trace_dispatch {
($method:expr, $handler:expr) => {
if $method == "length"
&& std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1")
{
eprintln!("[vm-trace] length dispatch handler={}", $handler);
}
};
}
mod arithmetic; mod arithmetic;
mod boxes; mod boxes;
mod boxes_array; mod boxes_array;

View File

@ -79,8 +79,9 @@ impl MirBuilder {
} }
let then_value_raw = self.build_expression(then_branch)?; let then_value_raw = self.build_expression(then_branch)?;
let then_exit_block = self.current_block()?; let then_exit_block = self.current_block()?;
let then_reaches_merge = !self.is_current_block_terminated();
let then_var_map_end = self.variable_map.clone(); let then_var_map_end = self.variable_map.clone();
if !self.is_current_block_terminated() { if then_reaches_merge {
// Scope leave for then-branch // Scope leave for then-branch
self.hint_scope_leave(0); self.hint_scope_leave(0);
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?; crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
@ -116,7 +117,8 @@ impl MirBuilder {
(void_val, None, None) (void_val, None, None)
}; };
let else_exit_block = self.current_block()?; let else_exit_block = self.current_block()?;
if !self.is_current_block_terminated() { let else_reaches_merge = !self.is_current_block_terminated();
if else_reaches_merge {
// Scope leave for else-branch // Scope leave for else-branch
self.hint_scope_leave(0); self.hint_scope_leave(0);
self.emit_instruction(MirInstruction::Jump { target: merge_block })?; self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
@ -144,8 +146,8 @@ impl MirBuilder {
let result_val = self.normalize_if_else_phi( let result_val = self.normalize_if_else_phi(
then_block, then_block,
else_block, else_block,
Some(then_exit_block), if then_reaches_merge { Some(then_exit_block) } else { None },
Some(else_exit_block), if else_reaches_merge { Some(else_exit_block) } else { None },
then_value_raw, then_value_raw,
else_value_raw, else_value_raw,
&pre_if_var_map, &pre_if_var_map,
@ -176,8 +178,8 @@ impl MirBuilder {
self.merge_modified_vars( self.merge_modified_vars(
then_block, then_block,
else_block, else_block,
then_exit_block, if then_reaches_merge { Some(then_exit_block) } else { None },
Some(else_exit_block), if else_reaches_merge { Some(else_exit_block) } else { None },
&pre_if_var_map, &pre_if_var_map,
&then_var_map_end, &then_var_map_end,
&else_var_map_end_opt, &else_var_map_end_opt,

View File

@ -283,8 +283,9 @@ impl super::MirBuilder {
t_id t_id
}; };
let then_exit_block = self.current_block()?; let then_exit_block = self.current_block()?;
let then_reaches_merge = !self.is_current_block_terminated();
let then_var_map_end = self.variable_map.clone(); let then_var_map_end = self.variable_map.clone();
if !self.is_current_block_terminated() { if then_reaches_merge {
self.hint_scope_leave(0); self.hint_scope_leave(0);
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?; crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
} }
@ -338,8 +339,9 @@ impl super::MirBuilder {
rhs_bool rhs_bool
}; };
let else_exit_block = self.current_block()?; let else_exit_block = self.current_block()?;
let else_reaches_merge = !self.is_current_block_terminated();
let else_var_map_end = self.variable_map.clone(); let else_var_map_end = self.variable_map.clone();
if !self.is_current_block_terminated() { if else_reaches_merge {
self.hint_scope_leave(0); self.hint_scope_leave(0);
self.emit_instruction(MirInstruction::Jump { target: merge_block })?; self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
} }
@ -350,24 +352,32 @@ impl super::MirBuilder {
self.start_new_block(merge_block)?; self.start_new_block(merge_block)?;
self.push_if_merge(merge_block); self.push_if_merge(merge_block);
// Result PHI (bool) // Result PHI (bool) — consider only reachable predecessors
let result_val = self.value_gen.next(); let mut inputs: Vec<(crate::mir::BasicBlockId, ValueId)> = Vec::new();
let inputs = vec![(then_exit_block, then_value_raw), (else_exit_block, else_value_raw)]; if then_reaches_merge { inputs.push((then_exit_block, then_value_raw)); }
if let Some(func) = self.current_function.as_mut() { if else_reaches_merge { inputs.push((else_exit_block, else_value_raw)); }
func.update_cfg(); let result_val = if inputs.len() >= 2 {
} if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) { if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs); crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
} }
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?; let dst = self.value_gen.next();
self.value_types.insert(result_val, MirType::Bool); self.emit_instruction(MirInstruction::Phi { dst, inputs })?;
self.value_types.insert(dst, MirType::Bool);
dst
} else if inputs.len() == 1 {
inputs[0].1
} else {
// Unreachable fallthrough: synthesize false (defensive)
crate::mir::builder::emission::constant::emit_bool(self, false)
};
// Merge modified vars from both branches back into current scope // Merge modified vars from both branches back into current scope
self.merge_modified_vars( self.merge_modified_vars(
then_block, then_block,
else_block, else_block,
then_exit_block, if then_reaches_merge { Some(then_exit_block) } else { None },
Some(else_exit_block), if else_reaches_merge { Some(else_exit_block) } else { None },
&pre_if_var_map, &pre_if_var_map,
&then_var_map_end, &then_var_map_end,
&Some(else_var_map_end), &Some(else_var_map_end),

View File

@ -13,7 +13,7 @@ impl MirBuilder {
&mut self, &mut self,
_then_block: super::BasicBlockId, _then_block: super::BasicBlockId,
else_block: super::BasicBlockId, else_block: super::BasicBlockId,
then_exit_block: super::BasicBlockId, then_exit_block_opt: Option<super::BasicBlockId>,
else_exit_block_opt: Option<super::BasicBlockId>, else_exit_block_opt: Option<super::BasicBlockId>,
pre_if_snapshot: &std::collections::HashMap<String, super::ValueId>, pre_if_snapshot: &std::collections::HashMap<String, super::ValueId>,
then_map_end: &std::collections::HashMap<String, super::ValueId>, then_map_end: &std::collections::HashMap<String, super::ValueId>,
@ -42,19 +42,26 @@ impl MirBuilder {
.unwrap_or(pre); .unwrap_or(pre);
// フェーズM: 常にPHI命令を使用no_phi_mode撤廃 // フェーズM: 常にPHI命令を使用no_phi_mode撤廃
// incoming の predecessor は "実際に merge に遷移してくる出口ブロック" を使用する // incoming の predecessor は "実際に merge に遷移してくる出口ブロック" を使用する
let then_pred = then_exit_block; let mut inputs: Vec<(super::BasicBlockId, super::ValueId)> = Vec::new();
let else_pred = else_exit_block_opt.unwrap_or(else_block); if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_v)); }
let merged = self.value_gen.next(); if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_v)); }
let inputs = vec![(then_pred, then_v), (else_pred, else_v)]; match inputs.len() {
if let Some(func) = self.current_function.as_mut() { 0 => {}
func.update_cfg(); 1 => {
let (_pred, v) = inputs[0];
self.variable_map.insert(name, v);
} }
_ => {
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) { if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs); crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
} }
let merged = self.value_gen.next();
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?; self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
self.variable_map.insert(name, merged); self.variable_map.insert(name, merged);
} }
}
}
// Ensure pinned synthetic slots ("__pin$...") have a block-local definition at the merge, // Ensure pinned synthetic slots ("__pin$...") have a block-local definition at the merge,
// even if their values did not change across branches. This avoids undefined uses when // even if their values did not change across branches. This avoids undefined uses when
@ -68,19 +75,26 @@ impl MirBuilder {
.as_ref() .as_ref()
.and_then(|m| m.get(pin_name.as_str()).copied()) .and_then(|m| m.get(pin_name.as_str()).copied())
.unwrap_or(*pre_val); .unwrap_or(*pre_val);
let then_pred = then_exit_block; let mut inputs: Vec<(super::BasicBlockId, super::ValueId)> = Vec::new();
let else_pred = else_exit_block_opt.unwrap_or(else_block); if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_v)); }
let merged = self.value_gen.next(); if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_v)); }
let inputs = vec![(then_pred, then_v), (else_pred, else_v)]; match inputs.len() {
if let Some(func) = self.current_function.as_mut() { 0 => {}
func.update_cfg(); 1 => {
let (_pred, v) = inputs[0];
self.variable_map.insert(pin_name.clone(), v);
} }
_ => {
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) { if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs); crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
} }
let merged = self.value_gen.next();
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?; self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
self.variable_map.insert(pin_name.clone(), merged); self.variable_map.insert(pin_name.clone(), merged);
} }
}
}
Ok(()) Ok(())
} }
/// Normalize Phi creation for if/else constructs. /// Normalize Phi creation for if/else constructs.
@ -129,32 +143,49 @@ impl MirBuilder {
// Else doesn't assign: use pre-if value if available // Else doesn't assign: use pre-if value if available
pre_then_var_value.unwrap_or(else_value_raw) pre_then_var_value.unwrap_or(else_value_raw)
}; };
// predecessor を then/else の exit ブロックに揃える // Build inputs from reachable predecessors only
let then_pred = then_exit_block_opt.unwrap_or(then_block); let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
let else_pred = else_exit_block_opt.unwrap_or(else_block); if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_for_var)); }
// Emit Phi for the assigned variable and bind it if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_value_for_var)); }
let inputs = vec![(then_pred, then_value_for_var), (else_pred, else_value_for_var)]; match inputs.len() {
if let Some(func) = self.current_function.as_mut() { 0 => {}
func.update_cfg(); 1 => {
// Direct bind (no PHI needed)
self.variable_map = pre_if_var_map.clone();
self.variable_map.insert(var_name, inputs[0].1);
return Ok(inputs[0].1);
} }
_ => {
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) { if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs); crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
} }
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?; self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
}
}
self.variable_map = pre_if_var_map.clone(); self.variable_map = pre_if_var_map.clone();
self.variable_map.insert(var_name, result_val); self.variable_map.insert(var_name, result_val);
} else { } else {
// No variable assignment pattern detected just emit Phi for expression result // No variable assignment pattern detected just emit Phi for expression result
let then_pred = then_exit_block_opt.unwrap_or(then_block); let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
let else_pred = else_exit_block_opt.unwrap_or(else_block); if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_raw)); }
let inputs = vec![(then_pred, then_value_raw), (else_pred, else_value_raw)]; if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_value_raw)); }
if let Some(func) = self.current_function.as_mut() { match inputs.len() {
func.update_cfg(); 0 => { /* leave result_val as fresh, but unused; synthesize void */
let v = crate::mir::builder::emission::constant::emit_void(self);
return Ok(v);
} }
1 => {
return Ok(inputs[0].1);
}
_ => {
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) { if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs); crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
} }
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?; self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
}
}
// Merge variable map conservatively to pre-if snapshot (no new bindings) // Merge variable map conservatively to pre-if snapshot (no new bindings)
self.variable_map = pre_if_var_map.clone(); self.variable_map = pre_if_var_map.clone();
} }