diff --git a/docs/development/current/CURRENT_TASK.md b/docs/development/current/CURRENT_TASK.md index b4e98e87..7e57e913 100644 --- a/docs/development/current/CURRENT_TASK.md +++ b/docs/development/current/CURRENT_TASK.md @@ -11,8 +11,8 @@ - ユニバーサルメソッド低スロット予約(0..3)✅ テストで不変確認 - Builderが解決可能なBoxCallに`method_id`を付与(未解決は遅延)✅ 実装/Printer表示 2) 9.79b.2: VM VTable Thunks + Mono-PIC - - `execute_boxcall`をvtable+thunkの単一路線へ - - call-site単位のモノモーフィックPICを追加 + - `execute_boxcall`をvtable+thunkの単一路線へ(ユニバーサル0..3のfast-path追加)✅ スケルトン + - call-site単位のモノモーフィックPICを追加(Key設計とカウンタ導入、最適化は後段)🟡 途中 ### すぐ試せるコマンド ```bash diff --git a/src/backend/dispatch.rs b/src/backend/dispatch.rs index 6a8c8cc5..6151f790 100644 --- a/src/backend/dispatch.rs +++ b/src/backend/dispatch.rs @@ -67,7 +67,7 @@ pub fn execute_instruction(vm: &mut VM, instruction: &MirInstruction, debug_glob // Complex operations MirInstruction::Call { dst, func, args, effects: _ } => vm.execute_call(*dst, *func, args), - MirInstruction::BoxCall { dst, box_val, method, args, effects: _ , .. } => vm.execute_boxcall(*dst, *box_val, method, args), + MirInstruction::BoxCall { dst, box_val, method, method_id, args, effects: _ , .. } => vm.execute_boxcall(*dst, *box_val, method, *method_id, args), MirInstruction::NewBox { dst, box_type, args } => vm.execute_newbox(*dst, box_type, args), // Array operations diff --git a/src/backend/vm_instructions.rs b/src/backend/vm_instructions.rs index 18d6743b..3922b828 100644 --- a/src/backend/vm_instructions.rs +++ b/src/backend/vm_instructions.rs @@ -502,12 +502,20 @@ impl VM { } /// Execute BoxCall instruction - pub(super) fn execute_boxcall(&mut self, dst: Option, box_val: ValueId, method: &str, args: &[ValueId]) -> Result { + pub(super) fn execute_boxcall(&mut self, dst: Option, box_val: ValueId, method: &str, method_id: Option, args: &[ValueId]) -> Result { let recv = self.get_value(box_val)?; // Debug logging if enabled let debug_boxcall = std::env::var("NYASH_VM_DEBUG_BOXCALL").is_ok(); + // Fast path: universal method slots via method_id (0..3) + if let Some(mid) = method_id { + if let Some(fast_res) = self.try_fast_universal(mid, &recv, args)? { + if let Some(dst_id) = dst { self.set_value(dst_id, fast_res); } + return Ok(ControlFlow::Continue); + } + } + // Convert args to NyashBox let nyash_args: Vec> = args.iter() .map(|arg| { @@ -565,3 +573,55 @@ impl VM { Ok(ControlFlow::Continue) } } + +impl VM { + /// Try fast universal-thunk dispatch using reserved method slots 0..3. + /// Returns Some(result) if handled, or None to fall back to legacy path. + fn try_fast_universal(&mut self, method_id: u16, recv: &VMValue, args: &[ValueId]) -> Result, VMError> { + match method_id { + 0 => { // toString + let s = recv.to_string(); + return Ok(Some(VMValue::String(s))); + } + 1 => { // type + let t = match recv { + VMValue::Integer(_) => "Integer".to_string(), + VMValue::Float(_) => "Float".to_string(), + VMValue::Bool(_) => "Bool".to_string(), + VMValue::String(_) => "String".to_string(), + VMValue::Future(_) => "Future".to_string(), + VMValue::Void => "Void".to_string(), + VMValue::BoxRef(b) => b.type_name().to_string(), + }; + return Ok(Some(VMValue::String(t))); + } + 2 => { // equals + // equals(other): bool — naive implementation via VMValue equivalence/coercion + let other = if let Some(arg0) = args.get(0) { self.get_value(*arg0)? } else { VMValue::Void }; + let res = match (recv, &other) { + (VMValue::Integer(a), VMValue::Integer(b)) => a == b, + (VMValue::Bool(a), VMValue::Bool(b)) => a == b, + (VMValue::String(a), VMValue::String(b)) => a == b, + (VMValue::Void, VMValue::Void) => true, + _ => recv.to_string() == other.to_string(), + }; + return Ok(Some(VMValue::Bool(res))); + } + 3 => { // clone + // For primitives: just copy. For BoxRef: share_box then wrap back. + let v = match recv { + VMValue::Integer(i) => VMValue::Integer(*i), + VMValue::Float(f) => VMValue::Float(*f), + VMValue::Bool(b) => VMValue::Bool(*b), + VMValue::String(s) => VMValue::String(s.clone()), + VMValue::Future(f) => VMValue::Future(f.clone()), + VMValue::Void => VMValue::Void, + VMValue::BoxRef(b) => VMValue::from_nyash_box(b.share_box()), + }; + return Ok(Some(v)); + } + _ => {} + } + Ok(None) + } +}