# Phase 11.5c: Coroutine実装による非同期処理の完成 ## 🎯 目標 async/await構文を追加し、JITレベルでcoroutineをstate machineに変換して高性能な非同期処理を実現する。 ## 📊 現状と目標 ### 現在の非同期処理 ```nyash // nowait文(スレッドベース) nowait result = heavyComputation() // ... local value = wait result // FutureBoxから取得 ``` ### 目標の構文 ```nyash // async/await(coroutineベース) 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, body: Box }, // 新規追加 AsyncFunction { name: String, params: Vec, body: Box }, AwaitExpression { expression: Box }, } ``` ### Step 2: MIR Coroutine命令 ```rust // mir/instruction.rs pub enum MirInstruction { // 既存命令... // Coroutine関連 /// Coroutine生成 CoroutineCreate { dst: ValueId, func: FunctionId, captures: Vec, }, /// Yield point(await) CoroutineYield { value: ValueId, resume_label: BasicBlockId, }, /// Coroutine再開 CoroutineResume { dst: Option, coroutine: ValueId, value: Option, }, /// Promise結合 PromiseAll { dst: ValueId, promises: Vec, }, } ``` ### Step 3: State Machine変換 ```rust // mir/coroutine_transform.rs pub struct CoroutineTransform { state_enum: HashMap, } /// 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 ) -> 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 { // 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>, base: BoxBase, } enum PromiseState { Pending(Vec)>>), Resolved(Box), Rejected(String), } impl PromiseBox { pub fn all(promises: Vec>) -> Box { // 全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.nyash # メモリプロファイル NYASH_COROUTINE_STATS=1 ./target/release/nyash bench/async_memory.nyash ``` ## 🚧 実装上の注意点 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並行処理ベンチマーク達成