phase_9_79b_2 (skeleton): VM BoxCall fast-path for universal slots\n- execute_boxcall now takes optional method_id\n- Fast-path thunks for toString/type/equals/clone\n- Dispatch updated; docs progress note in CURRENT_TASK
This commit is contained in:
@ -11,8 +11,8 @@
|
|||||||
- ユニバーサルメソッド低スロット予約(0..3)✅ テストで不変確認
|
- ユニバーサルメソッド低スロット予約(0..3)✅ テストで不変確認
|
||||||
- Builderが解決可能なBoxCallに`method_id`を付与(未解決は遅延)✅ 実装/Printer表示
|
- Builderが解決可能なBoxCallに`method_id`を付与(未解決は遅延)✅ 実装/Printer表示
|
||||||
2) 9.79b.2: VM VTable Thunks + Mono-PIC
|
2) 9.79b.2: VM VTable Thunks + Mono-PIC
|
||||||
- `execute_boxcall`をvtable+thunkの単一路線へ
|
- `execute_boxcall`をvtable+thunkの単一路線へ(ユニバーサル0..3のfast-path追加)✅ スケルトン
|
||||||
- call-site単位のモノモーフィックPICを追加
|
- call-site単位のモノモーフィックPICを追加(Key設計とカウンタ導入、最適化は後段)🟡 途中
|
||||||
|
|
||||||
### すぐ試せるコマンド
|
### すぐ試せるコマンド
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@ -67,7 +67,7 @@ pub fn execute_instruction(vm: &mut VM, instruction: &MirInstruction, debug_glob
|
|||||||
|
|
||||||
// Complex operations
|
// Complex operations
|
||||||
MirInstruction::Call { dst, func, args, effects: _ } => vm.execute_call(*dst, *func, args),
|
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),
|
MirInstruction::NewBox { dst, box_type, args } => vm.execute_newbox(*dst, box_type, args),
|
||||||
|
|
||||||
// Array operations
|
// Array operations
|
||||||
|
|||||||
@ -502,12 +502,20 @@ impl VM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Execute BoxCall instruction
|
/// Execute BoxCall instruction
|
||||||
pub(super) fn execute_boxcall(&mut self, dst: Option<ValueId>, box_val: ValueId, method: &str, args: &[ValueId]) -> Result<ControlFlow, VMError> {
|
pub(super) fn execute_boxcall(&mut self, dst: Option<ValueId>, box_val: ValueId, method: &str, method_id: Option<u16>, args: &[ValueId]) -> Result<ControlFlow, VMError> {
|
||||||
let recv = self.get_value(box_val)?;
|
let recv = self.get_value(box_val)?;
|
||||||
|
|
||||||
// Debug logging if enabled
|
// Debug logging if enabled
|
||||||
let debug_boxcall = std::env::var("NYASH_VM_DEBUG_BOXCALL").is_ok();
|
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
|
// Convert args to NyashBox
|
||||||
let nyash_args: Vec<Box<dyn NyashBox>> = args.iter()
|
let nyash_args: Vec<Box<dyn NyashBox>> = args.iter()
|
||||||
.map(|arg| {
|
.map(|arg| {
|
||||||
@ -565,3 +573,55 @@ impl VM {
|
|||||||
Ok(ControlFlow::Continue)
|
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<Option<VMValue>, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user