Phase 10.7/10.5c: include cycle detection (VM/Interpreter), minimal pyc IR→Nyash, String unification bridge (VM partial), add core plugins: RegexBox/EncodingBox/TOMLBox/PathBox + examples; wire nyash.toml; begin String interop for internal vs plugin boxes; update CURRENT_TASK.md

This commit is contained in:
Moe Charm
2025-08-30 23:47:08 +09:00
parent c13d9c045e
commit 4ae92cfb56
39 changed files with 3217 additions and 69 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.nyash
# Atomic最適化後
NYASH_ATOMIC_OPT=1 ./target/release/nyash bench.nyash
```
## 🚧 実装上の注意点
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.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並行処理ベンチマーク達成

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.nyash
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.nyash
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.nyash
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.nyash
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.nyash
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/
│ └── *.nyash (ソースコード)
├── 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,102 @@
# プラグインBoxの箱引数宣言方法
## 📊 nyash_box.tomlでの宣言
### 1. 基本的な箱引数の宣言
```toml
[HttpRequestBox.methods.respond]
id = 3
args = [ { name = "resp", type = "box" } ] # type = "box" で箱引数を宣言
returns = { type = "void" }
```
### 2. 引数の型一覧
| 型指定 | 説明 | TLVタグ |
|--------|------|---------|
| `"i64"` | 64ビット整数 | 3 |
| `"f64"` | 64ビット浮動小数点 | 5 |
| `"string"` | UTF-8文字列 | 6 |
| `"bool"` | 真偽値 | 1 |
| `"box"` | **箱(ハンドル)** | 8 |
### 3. 実際の使用例
#### NetプラグインのHttpRequestBox
```toml
[HttpRequestBox]
type_id = 21
[HttpRequestBox.methods.respond]
id = 3
args = [ { name = "resp", type = "box" } ] # HttpResponseBoxを受け取る
returns = { type = "void" }
```
使用方法Nyash
```nyash
local request = server.accept() // HttpRequestBox
local response = new HttpResponseBox() // 別のプラグインBox
response.setStatus(200)
request.respond(response) // 箱を引数として渡す!
```
#### 戻り値が箱の例
```toml
[HttpServerBox.methods.accept]
id = 3
args = []
returns = { type = "box" } # HttpRequestBoxを返す
```
## 🔧 C実装側での処理
### TLVデコード
```c
// HttpRequestBox.respondの実装例
case 3: { // respond
// 引数をデコード
if (args_len < 12) return -1; // header(4) + handle(8)
// TLVタグチェック
uint8_t tag = args[4];
if (tag != 8) return -1; // TAG_HANDLE = 8
// ハンドルデータ取得
uint32_t resp_type_id = *(uint32_t*)&args[8];
uint32_t resp_instance_id = *(uint32_t*)&args[12];
// HttpResponseBoxtype_id=22であることを確認
if (resp_type_id != 22) return -1;
// レスポンス処理...
}
```
## 💡 重要なポイント
### 1. 型安全性
- `type = "box"`は任意の箱を受け取れる
- 実装側で`type_id`チェックにより型安全性を確保
### 2. 相互運用性
- 異なるプラグイン間でも箱の受け渡しが可能
- ハンドルtype_id + instance_idにより参照
### 3. 宣言の簡潔さ
```toml
# シンプルな宣言
args = [ { name = "box_arg", type = "box" } ]
# 複数の箱引数も可能
args = [
{ name = "box1", type = "box" },
{ name = "box2", type = "box" },
{ name = "count", type = "i64" }
]
```
## 🎯 結論
プラグインBoxは`nyash_box.toml``type = "box"`と宣言するだけで、他の箱を引数に取ることができます。C ABIレベルではTLVハンドルタグ8として処理され、完全な相互運用性が実現されています。

View File

@ -0,0 +1,115 @@
# プラグインBoxは既に箱を引数に取れる
## 🎯 重要な発見
**プラグインBoxは既にC ABIレベルで箱を引数に取ることができます**
## 📊 実装の詳細
### 1. TLVプロトコルでのハンドルサポート
```rust
// TLVタグ定義
const TAG_HANDLE: u8 = 8; // プラグインハンドル用
// ハンドルエンコード関数
pub fn plugin_handle(buf: &mut Vec<u8>, type_id: u32, instance_id: u32) {
buf.push(TAG_HANDLE);
buf.push(0u8); // reserved
buf.extend_from_slice(&(8u16).to_le_bytes()); // size = 8
buf.extend_from_slice(&type_id.to_le_bytes()); // 4 bytes
buf.extend_from_slice(&instance_id.to_le_bytes()); // 4 bytes
}
```
### 2. プラグイン呼び出し時の処理
```rust
// Nyashコード
box1.process(box2, box3)
// ↓ VM/プラグインローダーでの処理
for arg in args {
if let Some(p) = arg.as_any().downcast_ref::<PluginBoxV2>() {
// 箱引数はハンドルとしてエンコード
encode::plugin_handle(&mut tlv, p.type_id, p.instance_id);
}
// ... 他の型の処理
}
// ↓ C ABIプラグイン側
int32_t nyash_plugin_invoke(
uint32_t type_id,
uint32_t method_id,
uint32_t instance_id,
const uint8_t* args, // TLVエンコードされた引数
size_t args_len,
uint8_t* result,
size_t* result_len
) {
// TLVデコード
uint8_t tag;
uint32_t arg_type_id, arg_instance_id;
if (decode_handle(args, &tag, &arg_type_id, &arg_instance_id)) {
// ハンドル引数を処理
// arg_type_id と arg_instance_id で箱を特定
}
}
```
## 🔄 実際の使用例
### Nyashレベル
```nyash
// FileBoxがStringBoxを引数に取る例
local file = new FileBox()
local path = new StringBox("/tmp/test.txt")
file.open(path) // StringBoxプラグインBoxを引数に
// ArrayBoxがMapBoxを引数に取る例
local array = new ArrayBox()
local map = new MapBox()
array.push(map) // MapBoxプラグインBoxを引数に
```
### プラグイン間の相互運用
```nyash
// NetBoxがJSONBoxを引数に取る例
local net = new NetBox()
local json = new JSONBox()
json.set("url", "https://api.example.com")
net.post(json) // JSONBoxを引数として渡す
```
## 💡 重要なポイント
### 1. ハンドルによる間接参照
- 箱の実体は渡さない(メモリ安全性)
- `(type_id, instance_id)`のペアで識別
- プラグイン側でハンドルから実体にアクセス
### 2. 型安全性
- `type_id`で型を識別可能
- 不正な型の場合はエラー返却
### 3. 所有権管理
- インスタンスIDで参照管理
- プラグイン間でも安全に共有
## 🎯 結論
**C ABIの制約があっても、ハンドル機構により箱は箱を引数に取れる**
これは既に実装済みの機能であり、プラグイン間での高度な連携が可能です。
### 埋め込みVMへの示唆
既存のTLVハンドル機構をそのまま使えば、埋め込みVMでも同じように箱引数をサポートできます
1. Nyashスクリプト内で箱を引数に使用
2. MIRバイトコードにBoxCall命令を含める
3. 埋め込みVMがTLVエンコードでC ABIプラグインを呼び出し
4. ハンドル経由で箱を渡す
**Everything is Box、そしてC ABIでも箱は箱を扱える**