fix(joinir): Phase 241-EX - Remove hardcoded 'sum' check from Pattern3

Remove legacy hardcoded 'sum' carrier validation that was blocking
array_filter patterns with different accumulator names (e.g., 'out').

Before: Pattern3 required carrier named 'sum' to exist
After: Pattern3 uses carrier_info generically (any carrier name works)

Test results:
- phase49_joinir_array_filter_smoke: PASS 
- phase49_joinir_array_filter_fallback: PASS 
- phase49_joinir_array_filter_ab_comparison: PASS 
- Full suite: 909/909 PASS, 0 FAIL

Also: Archive old roadmap documentation (67k lines moved to docs/archive/)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-11 00:48:42 +09:00
parent a7dbc15878
commit 811dfebf98
387 changed files with 106 additions and 5551 deletions

View File

@ -0,0 +1,200 @@
# Phase 11.5a: Write Barrier除去によるGC最適化
## 🎯 目標
JITコンパイル時にescape analysisを行い、不要なwrite barrierを除去してGC性能を大幅に向上させる。
## 📊 現状の問題
### 現在のVM実装
```rust
// すべてのrefset操作でbarrierが呼ばれる
pub fn execute_ref_set(&mut self, reference: ValueId, field: &str, value: ValueId)
-> Result<ControlFlow, VMError> {
// ... 値の設定 ...
// 常にwrite barrierが実行される
gc_write_barrier_site(&self.runtime, "RefSet");
Ok(ControlFlow::Continue)
}
```
### オーバーヘッド
- 単純な代入でも毎回barrier呼び出し
- Stack上のローカル変数でも不要にbarrier
- ループ内での大量のbarrier呼び出し
## 🚀 実装計画
### Step 1: Escape Analysis基盤
```rust
// mir/escape_analysis.rs
pub struct EscapeAnalysis {
// allocation site追跡
allocations: HashMap<ValueId, AllocInfo>,
// escape状態
escapes: HashSet<ValueId>,
// 解析結果キャッシュ
cache: HashMap<FunctionId, EscapeInfo>,
}
#[derive(Debug)]
struct AllocInfo {
location: BasicBlockId,
kind: AllocKind,
size: Option<usize>,
}
enum AllocKind {
NewBox, // new StringBox()
ArrayNew, // []
RefNew, // ユーザー定義Box
}
```
### Step 2: MIR解析
```rust
impl EscapeAnalysis {
/// 関数内でのescape解析
pub fn analyze_function(&mut self, func: &MirFunction) -> EscapeInfo {
// 1. allocation site収集
for (bb_id, bb) in &func.basic_blocks {
for inst in &bb.instructions {
match inst {
MirInstruction::NewBox { dst, .. } |
MirInstruction::ArrayNew { dst, .. } |
MirInstruction::RefNew { dst, .. } => {
self.allocations.insert(*dst, AllocInfo {
location: bb_id,
kind: self.classify_alloc(inst),
size: self.estimate_size(inst),
});
}
_ => {}
}
}
}
// 2. escape point検出
self.find_escape_points(func);
// 3. 結果集計
EscapeInfo {
non_escaping: self.collect_non_escaping(),
barrier_sites: self.collect_barrier_sites(),
}
}
fn find_escape_points(&mut self, func: &MirFunction) {
// return文でのescape
// 関数引数としてのescape
// グローバル変数へのescape
// プラグイン呼び出しでのescape
}
}
```
### Step 3: JIT統合
```rust
// jit/lower/builder.rs
impl<'a> LoweringBuilder<'a> {
fn emit_ref_set(&mut self, reference: Value, field: &str, value: Value) {
// escape解析結果を確認
let needs_barrier = self.escape_info
.map(|info| info.needs_barrier(reference))
.unwrap_or(true); // 解析なしなら保守的にbarrier
if needs_barrier {
// barrierあり
self.emit_gc_barrier(BarrierKind::Write);
} else {
// barrier除去
if self.config.trace_opt {
eprintln!("[JIT] barrier removed at {:?}", self.current_location());
}
}
// 実際のstore操作
self.emit_store(reference, field, value);
}
}
```
### Step 4: 最適化レベル設定
```rust
// 環境変数で制御
NYASH_JIT_ESCAPE_ANALYSIS=1 # escape analysis有効化
NYASH_JIT_BARRIER_OPT=1 # barrier最適化有効化
NYASH_JIT_BARRIER_STATS=1 # 統計出力
```
## 📈 期待される効果
### ベンチマーク例
```nyash
// 大量のローカル変数操作
function processData(n) {
local sum = 0
local temp = new MapBox()
loop(i < n) {
temp.set(i, i * 2) // escape analysisでbarrier除去
sum = sum + temp.get(i)
i = i + 1
}
return sum
}
```
### 性能改善予測
- ローカル変数操作: 90%以上のbarrier除去
- ループ内操作: 80%以上の高速化
- 全体的なGCオーバーヘッド: 50%削減
## 🔍 検証方法
### 1. Barrier統計
```json
{
"total_barriers": 10000,
"removed_barriers": 8500,
"removal_rate": 0.85,
"sites": {
"RefSet": { "total": 5000, "removed": 4800 },
"ArraySet": { "total": 3000, "removed": 2500 },
"MapSet": { "total": 2000, "removed": 1200 }
}
}
```
### 2. 性能測定
```bash
# barrier最適化なし
NYASH_JIT_ESCAPE_ANALYSIS=0 ./target/release/nyash --benchmark
# barrier最適化あり
NYASH_JIT_ESCAPE_ANALYSIS=1 ./target/release/nyash --benchmark
```
## 🚧 実装上の注意点
1. **保守的な解析**
- 不明な場合は必ずbarrierを残す
- プラグイン境界では常にbarrier
2. **デバッグ性**
- 除去したbarrierサイトを記録
- GCエラー時の診断情報
3. **段階的実装**
- まずローカル変数のみ
- 次にループ不変式
- 最後に関数間解析
## 🎉 完了基準
- [ ] Escape analysis基本実装
- [ ] MIR解析パス追加
- [ ] JIT統合
- [ ] ベンチマーク50%改善
- [ ] ドキュメント更新

View File

@ -0,0 +1,240 @@
# Phase 11.5b: Atomic操作最適化によるsync処理高速化
## 🎯 目標
Arc<Mutex>の重いロック操作を、可能な限り軽量なatomic操作に置き換えて性能を向上させる。
## 📊 現状の問題
### 現在の実装
```rust
// すべてのBox操作でMutexロック
pub fn get_field(&self, name: &str) -> Option<Box<dyn NyashBox>> {
let fields = self.fields.lock().unwrap(); // 重い!
fields.get(name).cloned()
}
// Read-onlyでも同じコスト
pub fn to_string(&self) -> String {
let value = self.value.lock().unwrap(); // 不要なロック!
value.clone()
}
```
### パフォーマンス問題
- Read操作でも排他ロックのオーバーヘッド
- 複数スレッドでのcontention
- Cache line bouncing
## 🚀 実装計画
### Step 1: Read-only path分析
```rust
// mir/readonly_analysis.rs
pub struct ReadOnlyAnalysis {
// メソッドのread-only性
readonly_methods: HashMap<(TypeId, String), bool>,
// フィールドのimmutability
immutable_fields: HashMap<(TypeId, String), bool>,
}
impl ReadOnlyAnalysis {
pub fn analyze_box_types(&mut self, registry: &BoxRegistry) {
// StringBox.length() -> read-only
self.mark_readonly("StringBox", "length");
self.mark_readonly("StringBox", "isEmpty");
// IntegerBox.value() -> read-only
self.mark_readonly("IntegerBox", "value");
// プラグインメソッドも解析
self.analyze_plugin_methods();
}
}
```
### Step 2: Atomic wrapper実装
```rust
// runtime/atomic_box.rs
pub struct AtomicBox<T: NyashBox> {
// Read-optimized RwLock
inner: Arc<RwLock<T>>,
// Atomic cache for immutable data
cached_string: AtomicPtr<String>,
cached_int: AtomicI64,
}
impl<T: NyashBox> AtomicBox<T> {
/// Lock-free read for cached values
pub fn read_cached(&self) -> Option<Box<dyn NyashBox>> {
// Atomic loadでキャッシュチェック
let ptr = self.cached_string.load(Ordering::Acquire);
if !ptr.is_null() {
unsafe {
let s = &*ptr;
return Some(Box::new(StringBox::new(s.clone())));
}
}
None
}
/// Optimized read path
pub fn read_optimized<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R
{
// Try read lock first (non-blocking)
if let Ok(guard) = self.inner.try_read() {
return f(&*guard);
}
// Fallback to regular read
let guard = self.inner.read().unwrap();
f(&*guard)
}
}
```
### Step 3: JIT最適化
```rust
// jit/lower/atomic_opt.rs
impl<'a> LoweringBuilder<'a> {
fn emit_box_method_call(&mut self,
box_val: Value,
method: &str,
args: &[Value]
) -> Value {
// Read-only解析結果確認
if self.readonly_info.is_readonly_method(box_val, method) {
// Atomic fast path
self.emit_atomic_read_path(box_val, method, args)
} else {
// 通常のMutexパス
self.emit_mutex_path(box_val, method, args)
}
}
fn emit_atomic_read_path(&mut self,
box_val: Value,
method: &str,
args: &[Value]
) -> Value {
// 1. Atomic loadでcacheチェック
let cache_ptr = self.emit_atomic_load(box_val, "cache");
// 2. Cache hit判定
let is_valid = self.emit_null_check(cache_ptr);
// 3. 条件分岐
let then_block = self.create_block();
let else_block = self.create_block();
self.emit_branch(is_valid, then_block, else_block);
// Cache hit: lock-free return
self.switch_to_block(then_block);
let cached = self.emit_load(cache_ptr);
self.emit_jump(merge_block);
// Cache miss: RwLock読み取り
self.switch_to_block(else_block);
let value = self.emit_rwlock_read(box_val, method);
self.emit_jump(merge_block);
// Merge
self.switch_to_block(merge_block);
self.emit_phi(vec![(cached, then_block), (value, else_block)])
}
}
```
### Step 4: Memory ordering最適化
```rust
// プラットフォーム別最適化
#[cfg(target_arch = "x86_64")]
fn emit_memory_fence(&mut self, ordering: Ordering) {
match ordering {
Ordering::Relaxed => {}, // x86は強いメモリモデル
Ordering::Acquire => self.emit_lfence(),
Ordering::Release => self.emit_sfence(),
Ordering::SeqCst => self.emit_mfence(),
}
}
#[cfg(target_arch = "aarch64")]
fn emit_memory_fence(&mut self, ordering: Ordering) {
// ARMは弱いメモリモデル
match ordering {
Ordering::Relaxed => {},
Ordering::Acquire => self.emit_dmb_ld(),
Ordering::Release => self.emit_dmb_st(),
Ordering::SeqCst => self.emit_dmb(),
}
}
```
## 📈 期待される効果
### ベンチマーク
```nyash
// Read-heavy workload
function sumStringLengths(strings) {
local total = 0
loop(s in strings) {
total = total + s.length() // Atomic最適化
}
return total
}
// 性能改善
// Before: 1000ms (Mutex contention)
// After: 100ms (Lock-free reads)
```
### 改善予測
- Read操作: 90%高速化
- Read/Write混在: 50%高速化
- マルチスレッド: スケーラビリティ大幅向上
## 🔍 検証方法
### 1. Lock統計
```json
{
"total_operations": 100000,
"mutex_locks": 10000,
"atomic_reads": 90000,
"lock_reduction": 0.9,
"contention_events": 50
}
```
### 2. プロファイリング
```bash
# Mutexプロファイル
NYASH_PROFILE_LOCKS=1 ./target/release/nyash bench.hako
# Atomic最適化後
NYASH_ATOMIC_OPT=1 ./target/release/nyash bench.hako
```
## 🚧 実装上の注意点
1. **正確性**
- Memory orderingの正しさ
- ABA問題の回避
- Weak pointer対応
2. **互換性**
- 既存APIの維持
- プラグインとの相互運用
3. **デバッグ性**
- Race condition検出
- Lock順序の追跡
## 🎉 完了基準
- [ ] Read-only分析実装
- [ ] AtomicBox wrapper実装
- [ ] JIT統合
- [ ] マルチスレッドベンチマーク
- [ ] プラットフォーム別最適化

View File

@ -0,0 +1,295 @@
# Phase 11.5c: Coroutine実装による非同期処理の完成
## 🎯 目標
async/await構文を追加し、JITレベルでcoroutineをstate machineに変換して高性能な非同期処理を実現する。
## 📊 現状と目標
### 現在の非同期処理
```nyash
// nowait文スレッドベース
nowait result = heavyComputation()
// ...
local value = wait result // FutureBoxから取得
```
### 目標の構文
```nyash
// async/awaitcoroutineベース
async function fetchData(url) {
local response = await httpGet(url)
local json = await response.json()
return json.data
}
// 複数の非同期処理
async function fetchAll(urls) {
local promises = []
loop(url in urls) {
promises.push(fetchData(url))
}
return await Promise.all(promises)
}
```
## 🚀 実装計画
### Step 1: AST拡張
```rust
// ast.rs
#[derive(Debug, Clone)]
pub enum ASTNode {
// 既存
Function { name: String, params: Vec<String>, body: Box<ASTNode> },
// 新規追加
AsyncFunction {
name: String,
params: Vec<String>,
body: Box<ASTNode>
},
AwaitExpression {
expression: Box<ASTNode>
},
}
```
### Step 2: MIR Coroutine命令
```rust
// mir/instruction.rs
pub enum MirInstruction {
// 既存命令...
// Coroutine関連
/// Coroutine生成
CoroutineCreate {
dst: ValueId,
func: FunctionId,
captures: Vec<ValueId>,
},
/// Yield pointawait
CoroutineYield {
value: ValueId,
resume_label: BasicBlockId,
},
/// Coroutine再開
CoroutineResume {
dst: Option<ValueId>,
coroutine: ValueId,
value: Option<ValueId>,
},
/// Promise結合
PromiseAll {
dst: ValueId,
promises: Vec<ValueId>,
},
}
```
### Step 3: State Machine変換
```rust
// mir/coroutine_transform.rs
pub struct CoroutineTransform {
state_enum: HashMap<FunctionId, StateEnum>,
}
/// async関数をstate machineに変換
impl CoroutineTransform {
pub fn transform_async_function(&mut self,
func: &MirFunction
) -> MirFunction {
// 1. await pointsを収集
let await_points = self.collect_await_points(func);
// 2. State enum生成
let states = self.generate_states(await_points);
// 3. State machine関数生成
let state_machine = self.build_state_machine(func, states);
// 4. Coroutine wrapper生成
self.wrap_as_coroutine(state_machine)
}
fn build_state_machine(&self,
func: &MirFunction,
states: Vec<State>
) -> MirFunction {
// switch(state) {
// case State0: ... goto await1 or return
// case State1: ... goto await2 or return
// ...
// }
let mut builder = MirBuilder::new();
// Coroutine state
let state_var = builder.emit_local("state");
let locals = builder.emit_local("locals");
// Main dispatch loop
let loop_bb = builder.create_block();
builder.emit_jump(loop_bb);
builder.switch_to_block(loop_bb);
let state = builder.emit_load(state_var);
// State dispatch
for (i, state) in states.iter().enumerate() {
let state_bb = builder.create_block();
builder.emit_case(state.id, state_bb);
builder.switch_to_block(state_bb);
self.emit_state_code(&mut builder, state);
}
builder.build()
}
}
```
### Step 4: JIT Coroutine最適化
```rust
// jit/lower/coroutine.rs
impl<'a> LoweringBuilder<'a> {
/// Coroutineのstack switching最適化
fn emit_coroutine_switch(&mut self,
from: Value,
to: Value
) {
if self.config.use_fast_switch {
// レジスタのみ保存(最適化)
self.emit_save_registers();
self.emit_switch_stack(to);
self.emit_restore_registers();
} else {
// フルコンテキスト保存
self.emit_full_context_save(from);
self.emit_full_context_restore(to);
}
}
/// Inline可能なawaitの検出
fn try_inline_await(&mut self,
await_expr: &MirInstruction
) -> Option<Value> {
// Promise.resolvedなら即値返却
if self.is_resolved_promise(await_expr) {
return Some(self.emit_immediate_value());
}
// 小さなasync関数ならインライン化
if self.is_small_async(await_expr) {
return Some(self.inline_async_call(await_expr));
}
None
}
}
```
### Step 5: ランタイムサポート
```rust
// boxes/promise_box.rs
pub struct PromiseBox {
state: Arc<Mutex<PromiseState>>,
base: BoxBase,
}
enum PromiseState {
Pending(Vec<Box<dyn FnOnce(Box<dyn NyashBox>)>>),
Resolved(Box<dyn NyashBox>),
Rejected(String),
}
impl PromiseBox {
pub fn all(promises: Vec<Box<PromiseBox>>) -> Box<PromiseBox> {
// 全Promise完了待ち
let result = PromiseBox::new();
let remaining = Arc::new(AtomicUsize::new(promises.len()));
for (i, promise) in promises.iter().enumerate() {
promise.then(move |value| {
// 結果収集
if remaining.fetch_sub(1, Ordering::SeqCst) == 1 {
result.resolve(collected_values);
}
});
}
Box::new(result)
}
}
```
## 📈 期待される効果
### パフォーマンス比較
```nyash
// Before: Thread-based
nowait results = []
loop(url in urls) {
nowait r = httpGet(url) // 新スレッド生成
results.push(r)
}
// After: Coroutine-based
async function fetchAll(urls) {
return await Promise.all(
urls.map(url => httpGet(url)) // Stack switching only
)
}
```
### 改善予測
- メモリ使用量: 1/100スレッドstack vs coroutine state
- コンテキストスイッチ: 1000倍高速
- 同時接続数: 10,000+対応可能
## 🔍 検証方法
### 1. Coroutine統計
```json
{
"total_coroutines": 10000,
"active_coroutines": 500,
"yield_count": 50000,
"average_yield_ns": 100,
"stack_memory_mb": 10
}
```
### 2. ベンチマーク
```bash
# 10000並行リクエスト
./target/release/nyash bench/async_stress.hako
# メモリプロファイル
NYASH_COROUTINE_STATS=1 ./target/release/nyash bench/async_memory.hako
```
## 🚧 実装上の注意点
1. **Stack管理**
- Segmented stack対応
- Stack overflow検出
- GC root scanning
2. **エラー伝播**
- async境界でのエラー
- Promise rejection chain
3. **デバッグ対応**
- async stack trace
- Coroutine状態可視化
## 🎉 完了基準
- [ ] async/await構文実装
- [ ] MIR coroutine変換
- [ ] JIT最適化
- [ ] Promise/PromiseBox実装
- [ ] 10000並行処理ベンチマーク達成

View File

@ -0,0 +1,80 @@
# Box-SSA Core-15 最終決定
Date: 2025-08-31
Status: **固定仕様** (Frozen Specification)
Summary: MIR命令セットを真の15個に統一
## 📊 問題と解決
### 混乱していた2案
1. **Gemini版15**: RefNew/RefGet/RefSet含む15個だがBox哲学に反する
2. **文書版Core-15**: 実は17個Box哲学に近いが数が合わない
### ChatGPT5の第三案で決着
```
{ Const, UnaryOp, BinOp, Compare, TypeOp,
Load, Store,
Jump, Branch, Return, Phi,
Call, NewBox, BoxCall, ExternCall }
```
## 🌟 革命的統一BoxCall
すべてのBox操作を**BoxCall**一本に統一:
| 旧命令 | 新BoxCall表現 |
|--------|---------------|
| RefGet(obj, field) | BoxCall(obj, "getField", field) |
| RefSet(obj, field, val) | BoxCall(obj, "setField", field, val) |
| ArrayGet(arr, idx) | BoxCall(arr, "get", idx) |
| ArraySet(arr, idx, val) | BoxCall(arr, "set", idx, val) |
| PluginInvoke(p, m, args) | BoxCall(p, m, args) |
## 💡 技術的インパクト
### 実装の簡素化
- **Verifier**: BoxCallのチェックのみ
- **最適化**: PIC/インライン化がBoxCallに集中
- **GCバリア**: BoxCallのLoweringで統一処理
- **削減効果**: 26→15命令42%削減)
### LLVM変換戦略AI会議の合意
1. **BoxCall最適化**: メソッドID + PICPolymorphic Inline Cache
2. **脱箱化**: 2表現SSAプリミティブ計算→必要時のみBox化
3. **GCバリア**: 世代別GCで若→若は省略
4. **注釈→属性**: 保守的マッピング(安全性優先)
## 🚀 実装への影響
### JIT→LLVM直行の決断
- Cranelift = 実はAOTだったJIT幻想
- 15命令なら機械的変換で十分
- Phase 9-10スキップ → Phase 11LLVM直行
### ChatGPT5の反応
```
Box-SSA Core-15を聞く
完璧と判断
無言でコーディング開始(議論の余地なし)
```
## 📝 今後の課題
1. **MIR注釈システム**: 命令数を増やさずに最適化ヒント付与(設計案のみ)
2. **LLVM実装**: inkwellセットアップから開始
3. **既存コード移行**: 26→15命令への段階的移行
## 🎉 結論
**Box-SSA Core-15**により「Everything is Box」哲学が完全開花
- 真の15命令達成
- 実装の劇的簡素化
- 最適化の統一的適用
これが「あほみたいに簡単」で「恐ろしく速い」Nyashの最終形態
---
詳細なAI会議記録は [archives/](archives/) フォルダに保存

View File

@ -0,0 +1,60 @@
# Phase 11.5 Current Status
Date: 2025-08-31
Status: Active Development → LLVM Implementation
## 🎯 本日の大革命Box-SSA Core-15
### MIR命令セットの固定
- 26命令 → **真の15命令**に統一
- すべてのBox操作を**BoxCall**に集約
- Everything is Box哲学の完全実現
詳細: [BOX_SSA_CORE_15_FINAL_DECISION.md](BOX_SSA_CORE_15_FINAL_DECISION.md)
## 📊 Phase 11.5 タスク状況
### ✅ 完了
1. **Write Barrier Removal** (11.5a)
- Escape Analysis基礎実装
- RefSet最適化
2. **Atomic Operations** (11.5b)
- 同期プリミティブ実装
- Memory ordering保証
3. **Coroutine/Async** (11.5c)
- Future/Await基本実装
- 非同期ランタイム統合
4. **Box-SSA Core-15仕様固定** (NEW!)
- MIR 15命令に統一
- BoxCall万能化
### 🚀 次のステップ
**Phase 11LLVM直行決定**
- Phase 9-10JITスキップ
- Cranelift削除 → inkwell導入
- 15命令の機械的LLVM変換
## 📁 ドキュメント構成
### メインドキュメント
- `BOX_SSA_CORE_15_FINAL_DECISION.md` - 本日の革命的決定
- `11.5a/b/c-*.md` - 各サブフェーズの実装ガイド
- `IMPLEMENTATION-GUIDE.md` - 全体実装指針
- `FIRST-FIVE-APPS.md` - アプリケーション例
### アーカイブ
- `archives/` - 詳細なAI会議記録
- 個別相談記録Gemini, Codex, ChatGPT5
- 詳細技術議論
## 🎉 成果
1. **MIR簡素化**: 26→15命令42%削減)
2. **実装統一**: BoxCallに全Box操作を集約
3. **戦略転換**: JIT幻想から解放→LLVM直行
これでPhase 11.5は概念的に完了し、LLVM実装Phase 11へ移行準備完了

View File

@ -0,0 +1,307 @@
# 🚀 First Five Apps - Nyashの実力を証明する最初の5本
## 🎯 概要
Phase 11.5完了を待たずに、**今すぐ作れる**実用アプリ5本で、Nyashの産業レベルの完成度を世に示します。
すべて「Everything is BoxPluginInvoke」で統一実装し、VM/JIT/AOT/WASMの全バックエンドで動作確認します。
## 📋 アプリケーション一覧
### 1. ny-echo最小CLI- 基本I/O検証
**目的**: I/O・StringBoxの道通し確認
```nyash
// apps/ny-echo/main.hako
static box Main {
main(args) {
local console = new ConsoleBox()
local options = parseArgs(args)
loop(true) {
local input = console.readLine()
if input == null { break }
local output = input
if options.get("upper") {
output = input.toUpperCase()
} else if options.get("lower") {
output = input.toLowerCase()
}
console.log(output)
}
}
}
```
**受入基準**:
- [ ] VM/JIT/AOT/GCオン・オフすべてでtrace_hash一致
- [ ] 100万行処理で性能劣化なし
- [ ] メモリリークなしGCカウンター確認
### 2. ny-jsonlintPython連携デモ- プラグイン統合
**目的**: PyRuntimeBox/PyObjectBox経由のPluginInvoke検証
```nyash
// apps/ny-jsonlint/main.hako
static box Main {
init { py, console }
main(args) {
me.py = new PyRuntimeBox()
me.console = new ConsoleBox()
local filename = args.get(1)
if filename == null {
me.console.error("Usage: ny-jsonlint <file.json>")
return 1
}
local file = new FileBox()
file.open(filename, "r")
local content = file.read()
file.close()
local result = me.py.eval("
import json
try:
json.loads(content)
'OK'
except Exception as e:
f'NG: {str(e)}'
", new MapBox().set("content", content))
me.console.log(result)
return result.startsWith("OK") ? 0 : 1
}
}
```
**受入基準**:
- [ ] OS差なく実行Windows/Linux/macOS
- [ ] --sealedモードで完全再現可能
- [ ] 大規模JSON10MBでも安定動作
### 3. ny-array-bench性能デモ- ベンチマーク基準
**目的**: ArrayBox map/reduce、StatsBox導入、性能可視化
```nyash
// apps/ny-array-bench/main.hako
static box Main {
init { stats }
main(args) {
me.stats = new StatsBox()
local sizes = [1000, 10000, 100000]
loop(size in sizes) {
me.benchArrayOps(size)
}
// 結果をJSON出力CI集計用
local result = me.stats.toJSON()
print(result)
}
benchArrayOps(size) {
local array = new ArrayBox()
// 1. 配列生成
me.stats.startTimer("create_" + size)
loop(i < size) {
array.push(i)
}
me.stats.endTimer("create_" + size)
// 2. map操作
me.stats.startTimer("map_" + size)
local doubled = array.map(|x| x * 2)
me.stats.endTimer("map_" + size)
// 3. reduce操作
me.stats.startTimer("reduce_" + size)
local sum = doubled.reduce(|a, b| a + b, 0)
me.stats.endTimer("reduce_" + size)
// VM基準の相対性能を記録
me.stats.recordRelative("vm", 1.0)
if IS_JIT { me.stats.recordRelative("jit", SPEEDUP) }
if IS_AOT { me.stats.recordRelative("aot", SPEEDUP) }
}
}
```
**受入基準**:
- [ ] VM=1.0x基準でJIT/AOTの倍率表示
- [ ] fallbacks=0完全最適化
- [ ] 結果JSON自動出力CI集計可能
### 4. ny-filegrep実用ミニ- ファイルI/O実用例
**目的**: BytesBox/FileBoxプラグインI/O、実用的なツール
```nyash
// apps/ny-filegrep/main.hako
static box Main {
init { pattern, recursive, results }
main(args) {
me.parseArgs(args)
me.results = new ArrayBox()
local path = args.getLast() || "."
me.searchPath(path)
// 結果表示
loop(result in me.results) {
print(result)
}
return me.results.length() > 0 ? 0 : 1
}
searchPath(path) {
local file = new FileBox()
if file.isDirectory(path) {
if me.recursive {
local entries = file.listDir(path)
loop(entry in entries) {
me.searchPath(path + "/" + entry)
}
}
} else {
me.searchFile(path)
}
}
searchFile(filepath) {
local file = new FileBox()
file.open(filepath, "r")
local lineNum = 0
loop(true) {
local line = file.readLine()
if line == null { break }
lineNum = lineNum + 1
if line.contains(me.pattern) {
me.results.push(filepath + ":" + lineNum + ":" + line)
}
}
file.close()
}
}
```
**受入基準**:
- [ ] Windows/Linux/macOSで同一結果
- [ ] 大規模ディレクトリ1万ファイル対応
- [ ] メモリ効率的(ストリーム処理)
### 5. ny-http-helloWASM/ネイティブ両対応)- Web実用例
**目的**: NetBoxプラグインとイベントループ、FutureBox活用
```nyash
// apps/ny-http-hello/main.hako
static box Main {
init { server, running }
main(args) {
local port = args.get(1) || "8080"
me.server = new HttpServerBox()
me.running = true
// シグナルハンドラー設定
registerSignal("SIGINT", || me.stop())
// サーバー起動
me.server.start(port.toInteger())
print("Server listening on http://localhost:" + port)
// リクエストループ
loop(me.running) {
nowait request = me.server.accept()
me.handleRequest(wait request)
}
me.server.stop()
return 0
}
handleRequest(request) {
local response = new HttpResponseBox()
if request.path() == "/" {
response.setStatus(200)
response.setHeader("Content-Type", "text/plain")
response.write("Hello from Nyash!")
} else {
response.setStatus(404)
response.write("Not Found")
}
request.respond(response)
}
stop() {
print("Shutting down...")
me.running = false
}
}
```
**受入基準**:
- [ ] 100req/s程度のスモーク通過
- [ ] 停止シグナルでクリーンfini
- [ ] WASMビルドでも動作制限付き
## 🎯 実装優先順位
1. **ny-echo** - 最小実装、CI基盤確立
2. **ny-array-bench** - 性能基準確立
3. **ny-jsonlint** - プラグイン統合実証
4. **ny-filegrep** - 実用性実証
5. **ny-http-hello** - Web対応実証
## 📊 成功指標
### 全体指標
- [ ] 5アプリすべてがVM/JIT/AOTで動作
- [ ] CIでの自動テスト確立
- [ ] ドキュメント・サンプル完備
### 性能指標
- [ ] JIT: VMの5倍以上高速
- [ ] AOT: VMの10倍以上高速
- [ ] メモリ使用量: 同等機能のPython比50%以下
### 品質指標
- [ ] ゼロクラッシュ1000回実行
- [ ] メモリリークなし(長時間実行)
- [ ] プラットフォーム差異なし
## 🚀 配布戦略
### リリース形式
```
nyash-apps-v1.0/
├── bin/
│ ├── ny-echo[.exe]
│ ├── ny-jsonlint[.exe]
│ ├── ny-array-bench[.exe]
│ ├── ny-filegrep[.exe]
│ └── ny-http-hello[.exe]
├── examples/
│ └── *.hako (ソースコード)
├── benchmarks/
│ └── results.json
└── README.md
```
### 展開先
- GitHub Releases
- Homebrew (macOS)
- Scoop (Windows)
- Docker Hub (コンテナ版)
これで「30日で作った言語」の実力を世界に示せます🎉

View File

@ -0,0 +1,191 @@
# Phase 11.5 実装ガイド - ChatGPT5向け
## 🎯 実装の全体像
Phase 11.5は、Nyashの性能を産業レベルに引き上げる最終段階です。3つの主要な最適化を行います
1. **Write Barrier除去** - GCオーバーヘッドを90%削減
2. **Atomic最適化** - sync処理を10倍高速化
3. **Coroutine実装** - 真の非同期処理を実現
## 📋 実装順序と依存関係
```mermaid
graph TD
A[11.5a: Write Barrier除去] --> D[統合テスト]
B[11.5b: Atomic最適化] --> D
C[11.5c: Coroutine実装] --> D
D --> E[Phase 11.5完了]
```
各タスクは独立して実装可能ですが、統合テストで相互作用を検証します。
## 🔧 技術的な実装詳細
### 1. Write Barrier除去の実装手順
#### Step 1: MIR拡張
```rust
// src/mir/escape_analysis.rs (新規作成)
use crate::mir::{MirFunction, MirInstruction, ValueId};
use std::collections::{HashMap, HashSet};
pub struct EscapeAnalysis {
allocations: HashMap<ValueId, AllocSite>,
escapes: HashSet<ValueId>,
}
impl EscapeAnalysis {
pub fn new() -> Self {
Self {
allocations: HashMap::new(),
escapes: HashSet::new(),
}
}
pub fn analyze(&mut self, func: &MirFunction) -> EscapeInfo {
// 実装のポイント:
// 1. NewBox, RefNew命令を追跡
// 2. Return, Call命令でescape判定
// 3. ループ不変式も考慮
}
}
```
#### Step 2: VM統合
```rust
// src/backend/vm_instructions.rs の修正
pub fn execute_ref_set(&mut self, reference: ValueId, field: &str, value: ValueId)
-> Result<ControlFlow, VMError> {
// 既存のコード...
// Escape analysisの結果を確認
if let Some(escape_info) = &self.escape_info {
if !escape_info.escapes(reference) {
// Barrierスキップ
return Ok(ControlFlow::Continue);
}
}
// 通常のbarrier処理
gc_write_barrier_site(&self.runtime, "RefSet");
Ok(ControlFlow::Continue)
}
```
### 2. Atomic最適化の実装手順
#### Step 1: BoxCore拡張
```rust
// src/box_trait.rs の修正
pub trait BoxCore: Send + Sync {
// 既存のメソッド...
/// Read-onlyメソッドかどうか
fn is_readonly_method(&self, method: &str) -> bool {
// デフォルトはfalse保守的
false
}
}
// 各Boxで実装
impl BoxCore for StringBox {
fn is_readonly_method(&self, method: &str) -> bool {
matches!(method, "length" | "isEmpty" | "charAt")
}
}
```
#### Step 2: Atomic wrapper
```rust
// src/runtime/atomic_box.rs (新規作成)
use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::Arc;
use parking_lot::RwLock; // より高速なRwLock
pub struct AtomicBox<T> {
inner: Arc<RwLock<T>>,
cache: AtomicPtr<CachedValue>,
}
```
### 3. Coroutine実装の実装手順
#### Step 1: Parser拡張
```rust
// src/parser/keywords.rs の修正
pub const RESERVED_WORDS: &[&str] = &[
// 既存のキーワード...
"async",
"await",
];
// src/parser/expressions.rs の修正
fn parse_function_declaration(&mut self) -> Result<ASTNode, ParseError> {
let is_async = self.consume_keyword("async");
// 既存のパース処理...
}
```
#### Step 2: MIR Coroutine変換
```rust
// src/mir/coroutine_transform.rs (新規作成)
pub fn transform_async_function(func: &MirFunction) -> MirFunction {
// State machine変換のアルゴリズム:
// 1. await箇所でstateを分割
// 2. ローカル変数をstate構造体に移動
// 3. switch文で状態遷移を実装
}
```
## 🎯 ChatGPT5への実装指示
### Phase 11.5a(最優先)
1. `src/mir/escape_analysis.rs`を作成
2. 基本的なallocation追跡を実装
3. VM統合でbarrier除去をテスト
4. ベンチマークで効果測定
### Phase 11.5b(次優先)
1. `BoxCore::is_readonly_method`を追加
2. 主要Boxで実装StringBox, IntegerBox
3. RwLock移行を段階的に実施
### Phase 11.5c(最後)
1. Parser拡張async/await
2. 基本的なPromiseBox実装
3. 簡単なasync関数の動作確認
## 📊 成功指標
各フェーズの完了基準:
### 11.5a: Write Barrier除去
- [ ] escape_analysis.rsが動作
- [ ] 簡単なループでbarrier除去確認
- [ ] ベンチマークで30%以上改善
### 11.5b: Atomic最適化
- [ ] Read-onlyメソッドの識別
- [ ] RwLock使用でread性能向上
- [ ] マルチスレッドベンチマーク改善
### 11.5c: Coroutine実装
- [ ] async/awaitがパース可能
- [ ] 簡単なasync関数が実行可能
- [ ] Promiseチェーンが動作
## 🚀 実装開始コマンド
```bash
# ブランチ作成
git checkout -b phase-11.5-jit-integration
# テスト駆動開発
cargo test escape_analysis
# ベンチマーク実行
./target/release/nyash --benchmark --iterations 1000
```
頑張ってください、ChatGPT5これが完成すれば、Nyashは本当に世界クラスの言語になります

View File

@ -0,0 +1,169 @@
# Phase 11.5: JIT完全統合 - sync/GC/非同期の最終実装
## 🎯 概要
Phase 11.5は、Nyashの全実行レイヤーインタープリター/MIR/VM/JITでsync処理、GC処理、非同期処理を完全に統合する最終フェーズです。
## 📊 現状分析2025-08-30
### ✅ 完了済み
1. **基本アーキテクチャ**
- Everything is Box哲学の完全実装
- インタープリター → MIR → VM → JIT パイプライン
- プラグインシステムC ABI/TLVハンドル
2. **sync処理**
- Arc<Mutex>/Arc<RwLock>による完全スレッドセーフ設計
- 全レイヤーでの一貫した同期化
3. **GC基礎**
- カウンティングGC実装NYASH_GC_COUNTING=1
- Read/Writeバリア実装
- VMセーフポイント
4. **非同期基礎**
- FutureBox/TimerBox実装
- SingleThreadScheduler
- nowait/wait文
## 🚀 Phase 11.5 タスク一覧
### 1. JIT sync処理統合
- [ ] **1.1 Atomic操作の最適化**
- Arc<Mutex>アクセスのJIT最適化
- Lock elision不要なロック除去
- Read-only pathでのロック回避
- [ ] **1.2 Memory ordering最適化**
- Relaxed/Acquire/Release semanticsの活用
- プラットフォーム別最適化x86/ARM
### 2. JIT GC統合
- [ ] **2.1 Write barrier除去**
- Escape analysisによる不要バリア検出
- Stack allocation最適化
- Generational hypothesis活用
- [ ] **2.2 Safepoint最適化**
- Loop safepoint挿入
- Call site safepoint
- Polling overhead削減
- [ ] **2.3 GC情報の伝播**
- Stack map生成
- Root set tracking
- Precise GC対応
### 3. JIT 非同期処理統合
- [ ] **3.1 Coroutine変換**
- async/await → state machine変換
- Stack switching最適化
- Continuation passing
- [ ] **3.2 スケジューラー統合**
- Work stealing queue
- CPU affinity最適化
- Yield point最適化
### 4. 統合テスト・ベンチマーク
- [ ] **4.1 性能測定**
- sync処理のオーバーヘッド測定
- GC pause time測定
- 非同期処理のレイテンシ測定
- [ ] **4.2 正確性検証**
- Race condition検出
- Memory leak検出
- Deadlock検出
## 📋 実装優先順位
### Phase 11.5a: Write barrier除去最重要
```rust
// 現在: すべてのBox操作でbarrier
vm.execute_ref_set() -> gc.barrier(Write)
// 目標: JITでescape analysisして除去
if !escapes_to_heap(value) {
// barrierスキップ
}
```
### Phase 11.5b: Atomic最適化
```rust
// 現在: Arc<Mutex>の重いロック
let value = box.lock().unwrap().clone();
// 目標: Read-onlyならatomic load
if is_read_only(box) {
atomic_load_relaxed(box)
}
```
### Phase 11.5c: Coroutine実装
```nyash
// 将来構文
async function fetchData() {
local result = await httpGet("...")
return result
}
```
## 🎯 成功基準
1. **性能向上**
- sync処理: 50%以上のロックオーバーヘッド削減
- GC: 90%以上のwrite barrier除去
- 非同期: ネイティブthread並みの性能
2. **互換性維持**
- 既存のNyashコードがそのまま動作
- プラグインシステムとの完全互換
3. **デバッグ性**
- JIT最適化の可視化NYASH_JIT_OPT_TRACE
- GC統計の詳細化
- 非同期処理のトレース
## 📅 実装スケジュール(推定)
- **Week 1-2**: Write barrier除去とescape analysis
- **Week 3**: Atomic操作最適化
- **Week 4**: Coroutine基礎実装
- **Week 5**: 統合テストとベンチマーク
- **Week 6**: ドキュメント化と最適化
## 🔧 技術的詳細
### Escape Analysis実装案
```rust
// MIR解析でallocサイトを特定
struct EscapeAnalysis {
allocations: HashMap<ValueId, AllocSite>,
escapes: HashSet<ValueId>,
}
impl EscapeAnalysis {
fn analyze(&mut self, func: &MirFunction) {
// 1. allocation site収集
// 2. data flow解析
// 3. escape判定
}
}
```
### JIT統合ポイント
```rust
// cranelift-jitでのbarrier除去
if !self.escape_info.escapes(value) {
// emit_call(gc_write_barrier) をスキップ
}
```
## 🎉 期待される成果
Phase 11.5完了により、Nyashは
- **産業レベルの性能**: GC pauseがマイクロ秒単位
- **真の並行性**: lock-free data structures対応
- **モダンな非同期**: async/await完全サポート
これにより、**30日で作られたとは思えない**世界クラスの言語が完成します!

View File

@ -0,0 +1,162 @@
# WASM実装の問題と改善計画
## 🚨 現状の問題
### 1. **2つのWASM実装が存在**
- **Rust→WASM**: `wasm-pack build`でNyashインタープリター全体をWASMに動作する
- **MIR→WASM**: `--compile-wasm`でNyashコードをWASMに変換ほぼ動かない
### 2. **MIR→WASM実装の問題点**
```rust
// src/backend/wasm/codegen.rs より
pub fn generate_module(...) -> Result<WasmModule, WasmError> {
// 基本的な命令しか実装されていない
// - 算術演算
// - 制御フロー
// - print文ホスト関数呼び出し
// 未実装:
// - Box操作NewBox, BoxCall, PluginInvoke
// - 配列操作
// - プラグインシステム
// - GC/メモリ管理
}
```
### 3. **根本的な設計問題**
- **Box抽象の表現困難**: Everything is BoxをWASMの型システムで表現できない
- **動的ディスパッチ**: BoxCallやPluginInvokeの実装が困難
- **GCの不在**: WASMにはGCがないWasmGC提案はまだ実験的
- **プラグインFFI**: C ABIをWASM環境で実現できない
## 📊 現状の実装状況
### 実装済み(動作するもの)
```nyash
// 基本的な算術
function add(a, b) {
return a + b
}
// 単純な制御フロー
function factorial(n) {
if n <= 1 { return 1 }
return n * factorial(n - 1)
}
// print文ホスト関数経由
print("Hello WASM")
```
### 未実装(動作しないもの)
```nyash
// Box操作
local str = new StringBox("hello") // ❌ NewBox未実装
str.toUpperCase() // ❌ BoxCall未実装
// 配列
local arr = [1, 2, 3] // ❌ 配列リテラル未実装
arr.push(4) // ❌ ArrayBox未実装
// プラグイン
local file = new FileBox() // ❌ PluginInvoke未実装
```
## 🤔 なぜRust→WASMは動くのか
```toml
# Cargo.toml
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
```
- **すべてのBox実装がそのままWASMに**: Arc<Mutex>も含めて
- **wasm-bindgenの魔法**: JavaScript↔Rust境界を自動生成
- **制限事項**: 一部のBoxTimerBox、FileBox等は除外
## 🚀 改善案
### Option 1: MIR→WASM実装の完成困難
```wat
;; BoxをWASMテーブルで管理
(table $boxes 1000 externref)
(global $next_box_id (mut i32) (i32.const 0))
;; NewBox実装
(func $new_string_box (param $str i32) (result i32)
;; 新しいBox IDを割り当て
(local $box_id i32)
(local.set $box_id (global.get $next_box_id))
;; JavaScriptでStringBoxを作成
(table.set $boxes
(local.get $box_id)
(call $js_create_string_box (local.get $str)))
;; IDを返す
(local.get $box_id)
)
```
**問題点**:
- JavaScript側にBox実装が必要
- 性能オーバーヘッドが大きい
- プラグインシステムとの統合困難
### Option 2: Rust→WASMの活用現実的
```rust
// NyashコードをRustに変換してからWASMに
nyash_code rust_code wasm
// 例:
// Nyash: local s = new StringBox("hello")
// Rust: let s = Box::new(StringBox::new("hello".to_string()));
// WASM: (自動生成)
```
### Option 3: WASMランタイムの埋め込み革新的
```wat
;; 最小VMをWASMに埋め込む
(module
;; MIRバイトコードを格納
(data (i32.const 0) "\01\02\03...")
;; VMインタープリター
(func $vm_execute
;; MIR命令をデコード・実行
)
;; エントリーポイント
(func (export "main")
(call $vm_execute)
)
)
```
## 🎯 推奨アプローチ
### Phase 1: 現状維持
- **Rust→WASM**: ブラウザでNyashを動かす用途で活用
- **MIR→WASM**: 実験的機能として残す
### Phase 2: Nyash→Rust変換
- NyashコードをRustに変換する仕組みを作る
- 生成されたRustコードをwasm-packでビルド
### Phase 3: WasmGC待ち
- WasmGC仕様が安定したら本格実装
- Box型システムをWasmGCで表現
## 📝 結論
現在のMIR→WASM実装は**実験的**なもので、実用レベルには達していません。一方、Rust→WASMは**すでに動作**しており、ブラウザでNyashを体験してもらうには十分です。
**当面は**
1. Rust→WASMでプレイグラウンド提供
2. ネイティブ実行VM/JIT/AOTに注力
3. WasmGCの成熟を待つ
これが現実的な戦略です!

View File

@ -0,0 +1,89 @@
# ChatGPT5の決定的アクション
Date: 2025-08-31
Summary: Box-SSA Core-15への収束と即座の実装開始
## 🎯 問題提起
> なおCore-15の最終セットは2案が文書にあります。どちらで凍結しますか
> - A) Gemini版15: RefNew/RefGet/RefSetを含む真の15個
> - B) CURRENT_TASKのCore-15: 実質17個15と言いながら
## 💡 第三の道Box-SSA Core-15
ChatGPT5の革命的提案
```
{ Const, UnaryOp, BinOp, Compare, TypeOp,
Load, Store,
Jump, Branch, Return, Phi,
Call, NewBox, BoxCall, ExternCall }
```
### 核心的洞察
**すべてのBox操作をBoxCallに統一**
- `RefNew``NewBox`
- `RefGet``BoxCall(obj, "getField", ...)`
- `RefSet``BoxCall(obj, "setField", ...)`
- `ArrayGet/ArraySet``BoxCall(arr, "get"/"set", ...)`
- `PluginInvoke``BoxCall(plugin, "invoke", ...)`
## 🚀 即座の実装開始
### 無言のコーディング
ChatGPT5は議論の余地なしと判断し、即座にMIR命令の列挙型を更新
```diff
&[
- "Copy", // 削除SSAで不要
- "RefNew", // 削除NewBoxに統合
- "RefGet", // 削除BoxCallに統合
- "RefSet", // 削除BoxCallに統合
+ "TypeOp", // 追加!型演算
+ "Phi", // 追加SSA必須
+ "NewBox", // 追加Box生成
+ "BoxCall", // 追加!万能呼び出し
]
```
### JIT→LLVM直行の判断
**現状認識**
- Cranelift = 実はAOTだったJIT幻想
- 15命令なら機械的変換で十分
- JITの複雑さ < LLVMの確実な高速化
**戦略転換**
```
旧計画: Phase 9JIT → Phase 10最適化 → Phase 11LLVM
新計画: Phase 9-10スキップ → Phase 11LLVM直行
```
## 📊 実装の約束事
### Verifier必須チェック
1. Box field直Load/Store検出禁止
2. 必要箇所のwrite barrier挿入検証
3. ExternCallのattr必須化
### Loweringの役割
- BoxCall 形状ガード 直アクセス バリア縮約
- VM: Phi展開簡易PIC
- LLVM: PICガードは最適化で潰れて素の命令列へ
## 🎉 結論
> 固定は "Box-SSA Core-15"。Aの Ref* は捨てるBの専用命令は BoxCall に吸収して15個に収斂。これで「簡単さ表面の一枚」「速さLowering/最適化」で分離でき、VMとAOTとFFIを**一本の ABI**で貫けるにゃ。
## 💻 ChatGPT5の心境
```nyash
if (命令数 == 15 && 設計 == "完璧") {
議論.skip()
実装.start() // 即座に!
}
```
この瞬間ChatGPT5はこれ以上の議論は時間の無駄と判断し無言でコーディングを開始したエンジニアが最高の設計に出会った時の最も純粋な反応である

View File

@ -0,0 +1,125 @@
# Codex先生のMIR→LLVM技術的深掘り
Date: 2025-08-31
Source: codex exec コマンドによる技術相談
## 質問内容
MIR15命令でEverything is Box哲学を実現。注釈システムで最適化ヒントを付与。
### 技術的課題
1. BoxCallの最適化PIC実装の具体的なLLVM IRパターン
2. 脱箱化戦略IntegerBox(42) → i64への変換タイミング
3. GCバリア最小化世代別GCでの若い世代→若い世代のバリア省略
4. 注釈→LLVM属性変換安全性の保証方法
5. インライン展開BoxCallのインライン基準
## Codex先生の技術的実装アプローチ
### 1. BoxCall + PICPolymorphic Inline Cache
#### モモルフィックPIC IR例
```llvm
; グローバルPIC
@pic_foo_site123 = internal global { i64, i8* } { 0, null }
; ガード + 直呼び
%cid = load i64, i64* %receiver_class_id
%pic_cls = load i64, i64* getelementptr({i64,i8*}, {i64,i8*}* @pic_foo_site123, i32 0, i32 0)
%hit = icmp eq i64 %cid, %pic_cls
%likely = call i1 @llvm.expect.i1(i1 %hit, i1 true)
br i1 %likely, label %fast, label %miss, !prof !{!"branch_weights", i32 10000, i32 1}
fast:
%callee = load i8*, i8** getelementptr({i64,i8*}, {i64,i8*}* @pic_foo_site123, i32 0, i32 1)
%fn = bitcast i8* %callee to %RetTy (%ObjTy*, ... )*
%r = call fastcc %RetTy %fn(%ObjTy* %recv, ...)
br label %cont
miss:
; cold, 非インライン
%r2 = call coldcc %RetTy @nyash_pic_miss_foo(%ObjTy* %recv, i64 %method_id, ...)
br label %cont
```
#### PIC更新の安全化
- 1-ワードのバージョンでRCU風プロトコル
- `store atomic i64 ver=odd (acq_rel)`→フィールド更新→`store atomic i64 ver=even (release)`
- リーダは一貫性確認、失敗時はmissへフォールバック
### 2. 脱箱化Unboxing戦略
#### 2表現SSA
- MIRで各Box値に「プリミティブSSAi64」と「Box化遅延ード」の二重表現
- `IntegerBox(42)` → 直ちに`i64 42`としてSSA化
- Boxが必要な境界汎用コンテナ格納、越関数ABI等直前でのみBox化
#### 実装例
```llvm
; 算術は全て i64
%a = add i64 %x, %y
; 必要になった地点でのみ実体化
%box = call %ObjTy* @nyash_make_int(i64 %a) ; ここでのみGC対象生成
call void @vector_push(%Vec* %v, %ObjTy* %box)
```
### 3. GCバリア最小化
#### Write barrier IRパターン
```llvm
; slot: i8** への書き込み
store i8* %val, i8** %slot
; TLSにNursery境界を保持
%low = load i64, i64* @nyash_tls_nursery_low
%high = load i64, i64* @nyash_tls_nursery_high
%yo_obj = and (icmp_uge %obj_i, %low), (icmp_ult %obj_i, %high)
%yo_val = and (icmp_uge %val_i, %low), (icmp_ult %val_i, %high)
%need_barrier = and (not %yo_obj), %yo_val ; 老→若のみ
%likely0 = call i1 @llvm.expect.i1(i1 %need_barrier, i1 false)
br i1 %likely0, label %barrier, label %cont, !prof !{!"branch_weights", 1, 10000}
barrier:
call fastcc void @nyash_card_mark(i8* %obj, i8** %slot, i8* %val) cold
br label %cont
```
### 4. 注釈→LLVM属性変換
#### 安全性担保の原則
- 原則Nyash注釈は「保守的に弱めに」マップ
- 検証不十分なら一段弱い属性を使用
#### マッピング例
| Nyash注釈 | LLVM属性 | 条件 |
|-----------|----------|------|
| `@no_escape` | `nocapture` | エスケープしないことを静的証明 |
| `@pure` | `readonly` | 副作用なしを保証 |
| `@pure` + 強条件 | `readnone speculatable` | メモリ不読+例外なし |
| `@nonnull` | `nonnull` | NULL不可を型システムで保証 |
### 5. インライン展開戦略
#### BoxCallの基準
-モルフィックPICかつヒット率高>90%)→ インライン
- コストモデルcall/ret + 間接分岐除去 + 逃げないBoxの削除
- メガモルフィック/低ヒット率は非インライン
#### 再帰的Box呼び出し最適化
```llvm
; 自己再帰でTCO
musttail call fastcc %RetTy @callee(%ObjTy* %recv, ...)
ret %RetTy %r
```
## 実装のこつ
1. **PICグローバル**`dso_local`/`internal`、更新局所性を確保
2. **ABI二系統**Box ABI/Primitive Fast-ABIを明示
3. **GC統合**`gc "statepoint-nyash"`を関数定義に付与
4. **最適化ヒント**`llvm.expect``!prof`を併用
## 結論
> 15命令は実装・最適化・GC統合の観点でよく均衡したミニマル核です。Box統一は開発生産性と実装単純性を大きく押し上げますが、性能面のボトルネックは脱箱・AA強化・適切なGC統合バリア/セーフポイント/原子性)で解消してください。
Codex先生は具体的なLLVM IRパターンとともに、実装可能で保守性の高い設計を提示してくれました。

View File

@ -0,0 +1,91 @@
# Gemini先生のMIR→LLVM変換コンサルテーション
Date: 2025-08-31
Source: gemini -p コマンドによる相談
## 質問内容
Nyashプログラミング言語のMIR→LLVM変換計画について
- MIRを26命令から15命令に削減中
- Everything is Box哲学
- 注釈システムでヒントを付与
### 15命令の内訳
- 基本演算(5): Const, UnaryOp, BinOp, Compare, TypeOp
- メモリ(2): Load, Store
- 制御(4): Branch, Jump, Return, Phi
- Box(3): NewBox, BoxCall, PluginInvoke
- 配列(2): ArrayGet, ArraySet
- 外部(1): ExternCall
## Gemini先生の回答
### 1. BoxCall最適化の最良アプローチ
**結論**: 静的解析による**メソッドIDスロットベースのディスパッチ**を主軸とし、解決できない場合に**PICPolymorphic Inline Cache**を組み合わせる
**理由**:
- Nyashはすでに`method_id`(スロット)を用いた最適化に着手
- 型が静的に推論できる場合に非常に高速
- 動的な呼び出しに対してはPICが有効実績ある手法
- vtable案も有力だが、`Everything is Box`の柔軟性を損なう可能性
**提案**:
1. MIRコンパイラ強化より多くの`BoxCall``method_id`付きに変換
2. PICの高度化Mono-PICから多相Polymorphic/メガモーフMegamorphic
3. LLVM IR生成時の戦略を明確化
### 2. GCバリアの効率的な挿入戦略
**結論**: **Store, ArraySet, PluginInvoke**のうち、**ヒープ上のBoxオブジェクトへのポインタ書き込み**が発生する可能性のある箇所にのみライトバリアを挿入
**提案**:
1. MIRレベルでの挿入条件付きで`GCBarrier`命令を挿入する最適化パス
2. 条件:
- 書き込まれる値がポインタBoxである
- 書き込み先がヒープ上のオブジェクトである
3. LLVM IR生成時`nyash.gc.barrier_write`シンボルの呼び出しに変換
### 3. 脱箱化Box→プリミティブのタイミング
**結論**: **型に関する注釈**を最大限に活用し、**MIRレベルの最適化パス**で実施
**提案**:
1. 注釈の活用:`#[primitive_type="i64"]`のようなヒント
2. MIR最適化パス
- 型推論と注釈に基づく安全な範囲の特定
- `NewBox`→プリミティブ値への置換
- `BoxCall`→直接的なLLVM演算への置換
3. LLVM IR生成時脱箱化された変数はプリミティブ型として表現
### 4. LLVM最適化パスの推奨構成
**推奨構成**:
1. 標準的な最適化パス(必須):
- `mem2reg`: SSA形式の基本
- `instcombine`: 冗長な命令の結合
- `gvn`: グローバルな共通部分式削除
- `sccp`: 定数畳み込みと到達不能コード削除
- `licm`: ループ不変コード移動
- `indvars`: ループ帰納変数単純化
- `loop-unroll`: ループ展開
2. Nyash特有のカスタムパス推奨
- Box化関連の除去
- ランタイムコール最適化
### 5. 注釈システムからLLVM属性への変換で注意点
**結論**: Nyash注釈のセマンティクスとLLVM属性のセマンティクスが完全に一致するかを慎重に検証し、**安全な属性から段階的に導入**
**注意点**:
- `noalias`: 誤用は未定義動作を引き起こす
- `!tbaa`: Box統一モデルでの工夫が必要
- `!range`: 数値注釈から生成可能
- 検証:安全な属性(`noundef`, `nonnull`)から開始
## 総評
> これらの提案が、NyashのLLVMバックエンド開発を加速させる一助となれば幸いです。
Gemini先生は、Nyashの「Everything is Box」哲学を理解した上で、実践的かつ段階的なアプローチを提案してくれました。特にPICとメソッドIDの組み合わせ、MIRレベルでの脱箱化は非常に有効な戦略です。