188 lines
5.4 KiB
Markdown
188 lines
5.4 KiB
Markdown
|
|
# Codex先生のBoxCall拡張分析 (2025-09-01)
|
|||
|
|
|
|||
|
|
## 質問内容
|
|||
|
|
|
|||
|
|
Nyash ABI実装の具体的アプローチについて技術相談です。
|
|||
|
|
|
|||
|
|
【背景】
|
|||
|
|
前回の議論で、C ABIとNyash ABIの両方をサポートする方向性が見えました。実装方法について新しいアイデアがあります。
|
|||
|
|
|
|||
|
|
【BoxCall拡張による統合案】
|
|||
|
|
MIR命令を増やさず、既存のBoxCallを自然に拡張する案です:
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
// 現在のBoxCall
|
|||
|
|
MirInstruction::BoxCall {
|
|||
|
|
receiver: Value,
|
|||
|
|
method: String,
|
|||
|
|
args: Vec<Value>,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提案:最小限の拡張
|
|||
|
|
MirInstruction::BoxCall {
|
|||
|
|
receiver: Value,
|
|||
|
|
method: String,
|
|||
|
|
args: Vec<Value>,
|
|||
|
|
abi_hint: Option<AbiType>, // 追加
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
【実装の流れ】
|
|||
|
|
1. MIRビルダー:プラグインBoxならABIヒント付与
|
|||
|
|
2. VM実行時:receiver.type_idから適切なABI選択
|
|||
|
|
3. プラグインローダー:nyash.tomlでABI指定可能
|
|||
|
|
|
|||
|
|
【この案の利点】
|
|||
|
|
- MIR命令数は15個維持(Everything is Box哲学)
|
|||
|
|
- 既存コード無変更(後方互換)
|
|||
|
|
- プラグインごとに段階的移行可能
|
|||
|
|
- JITでABI別最適化も可能
|
|||
|
|
|
|||
|
|
【質問】
|
|||
|
|
1. このBoxCall拡張案は設計として健全でしょうか?
|
|||
|
|
2. abi_hintは本当に必要?VM実行時の型判定で十分?
|
|||
|
|
3. 将来的な拡張(WASM等)にも対応できる設計か?
|
|||
|
|
4. パフォーマンス影響をどう評価すべきか?
|
|||
|
|
|
|||
|
|
実装の観点から、MIR層でのabi_hint追加とVM層でのABI判定について深く分析してください。特に既存実装への影響を最小化する方法を考慮して。
|
|||
|
|
|
|||
|
|
## Codex先生の回答
|
|||
|
|
|
|||
|
|
### コードベース分析
|
|||
|
|
|
|||
|
|
まず、現在のMIR/VM実装を確認:
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
// 現在のMirInstruction::BoxCall定義
|
|||
|
|
BoxCall {
|
|||
|
|
dst: Option<ValueId>,
|
|||
|
|
box_val: ValueId,
|
|||
|
|
method: String,
|
|||
|
|
method_id: Option<u16>, // Universal method用
|
|||
|
|
args: Vec<ValueId>,
|
|||
|
|
effects: EffectMask,
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
プラグインローダーはすでにnyash.tomlから型情報を読み込んでおり、VM実行時に利用可能。
|
|||
|
|
|
|||
|
|
### 核心的な洞察
|
|||
|
|
|
|||
|
|
**abi_hintは実は不要かもしれない!**
|
|||
|
|
|
|||
|
|
理由:
|
|||
|
|
1. VM実行時にreceiver.type_idから型情報を取得可能
|
|||
|
|
2. プラグインローダーが既にABI情報を保持している
|
|||
|
|
3. MIR層を変更せずに済む(15命令維持)
|
|||
|
|
|
|||
|
|
### 実装提案
|
|||
|
|
|
|||
|
|
#### Option A: 最小限実装(MIR無変更)
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
// VM層での実装
|
|||
|
|
fn execute_boxcall(&mut self, dst: Option<ValueId>, box_val: ValueId, method: &str, args: &[ValueId]) -> Result<ControlFlow, VMError> {
|
|||
|
|
let receiver = self.get_value(box_val)?;
|
|||
|
|
let type_id = receiver.get_type_id();
|
|||
|
|
|
|||
|
|
// プラグインローダーから型情報取得
|
|||
|
|
if let Some(plugin_info) = self.runtime.get_plugin_info(type_id) {
|
|||
|
|
match plugin_info.abi.as_str() {
|
|||
|
|
"c" => self.call_c_abi_plugin(plugin_info, method, args),
|
|||
|
|
"nyash" => self.call_nyash_abi_plugin(plugin_info, method, args),
|
|||
|
|
_ => self.call_c_abi_plugin(plugin_info, method, args), // fallback
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// ビルトインBox処理(既存のまま)
|
|||
|
|
self.execute_builtin_method(receiver, method, args)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Option B: 将来の拡張性を考慮
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
// MIRに汎用メタデータ追加(ABIに限定しない)
|
|||
|
|
MirInstruction::BoxCall {
|
|||
|
|
receiver: Value,
|
|||
|
|
method: String,
|
|||
|
|
args: Vec<Value>,
|
|||
|
|
metadata: Option<u32>, // 汎用的な最適化ヒント
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### JIT/AOT最適化の観点
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
// JIT時の特化
|
|||
|
|
match type_info.abi {
|
|||
|
|
Some("c") => {
|
|||
|
|
// 直接call命令生成
|
|||
|
|
builder.emit_direct_call(symbol, args);
|
|||
|
|
}
|
|||
|
|
Some("nyash") => {
|
|||
|
|
// NyashValue pack/unpackを含めてインライン化
|
|||
|
|
let packed = builder.emit_pack_nyash_values(args);
|
|||
|
|
builder.emit_call_with_abi(symbol, packed);
|
|||
|
|
}
|
|||
|
|
_ => {
|
|||
|
|
// 汎用パス(VM呼び出し)
|
|||
|
|
builder.emit_vm_boxcall(receiver, method, args);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### パフォーマンス評価方法
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
// ベンチマーク設計
|
|||
|
|
fn benchmark_abi_comparison() {
|
|||
|
|
// 1. 高頻度呼び出し(math operations)
|
|||
|
|
measure_time("C ABI", || {
|
|||
|
|
for _ in 0..1_000_000 {
|
|||
|
|
math_add_c_abi(1.0, 2.0);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
measure_time("Nyash ABI", || {
|
|||
|
|
for _ in 0..1_000_000 {
|
|||
|
|
math_add_nyash_abi(pack(1.0), pack(2.0));
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 2. 複雑な型(string operations)
|
|||
|
|
// 3. プラグイン初期化コスト
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 結論と推奨事項
|
|||
|
|
|
|||
|
|
1. **abi_hintは不要** - VM実行時の型判定で十分
|
|||
|
|
2. **MIR層は無変更** - 15命令の美しさ維持
|
|||
|
|
3. **将来拡張は型システム経由** - WASMもプラグイン型として追加
|
|||
|
|
4. **段階的実装**:
|
|||
|
|
- Week 1: nyash.toml拡張 + VM分岐
|
|||
|
|
- Week 2: ベンチマーク + 最適化
|
|||
|
|
- Week 3: JIT特化(必要なら)
|
|||
|
|
|
|||
|
|
### 実装の具体的ステップ
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
Step 1: nyash.toml拡張
|
|||
|
|
- LibraryDefinition に abi: Option<String> 追加
|
|||
|
|
- デフォルトは "c"
|
|||
|
|
|
|||
|
|
Step 2: プラグインローダー
|
|||
|
|
- PluginInfo 構造体に abi フィールド追加
|
|||
|
|
- ロード時に保存
|
|||
|
|
|
|||
|
|
Step 3: VM execute_boxcall
|
|||
|
|
- 型判定でABI分岐
|
|||
|
|
- call_c_abi / call_nyash_abi メソッド追加
|
|||
|
|
|
|||
|
|
Step 4: テスト
|
|||
|
|
- 同一機能の C/Nyash 両実装
|
|||
|
|
- 性能比較測定
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
この最小限アプローチなら、既存コードへの影響を最小化しつつ、将来の拡張性も確保できます。
|