Files

5.7 KiB
Raw Permalink Blame History

Nyash VM 実行基盤ガイド(更新)

  • プラグインBox引数の最小対応を追加TLV: BoxRef
  • TLVタグ: 1=Bool, 2=I32, 3=I64, 4=F32, 5=F64, 6=String, 7=Bytes, 8=Handle(BoxRef)
    • BoxRefはプラグインBox参照type_id:u32, instance_id:u32を8バイトでエンコード
    • ユーザー定義/複雑なBoxは当面一部非対応toStringフォールバック。標準Boxはプラグイン経由で統一

現状のルーティングPlugin-First:

  • User-defined: MIR関数{Box}.{method}/{N}) にCall化関数存在時。それ以外はBoxCall。
  • Plugin: BoxCall → PluginInvokemethod_idが解決可能→ それ以外は名前解決で PluginHost.invoke_instance_method。

今後のタスク:

  • VM側のfrom Parent.method対応Builder/VM両対応
  • TLVの型拡張Float/配列/BoxRef戻り値など

🧮 VM実行統計NYASH_VM_STATS / JSON

VMは命令カウントと実行時間を出力できます。

使い方CLIフラグ:

# 人間向け表示
nyash --backend vm --vm-stats program.hako

# JSON出力
nyash --backend vm --vm-stats --vm-stats-json program.hako

環境変数(直接指定):

NYASH_VM_STATS=1 ./target/debug/nyash --backend vm program.hako
NYASH_VM_STATS=1 NYASH_VM_STATS_JSON=1 ./target/debug/nyash --backend vm program.hako
# 代替: NYASH_VM_STATS_FORMAT=json

出力は total(総命令数), elapsed_ms(経過時間), counts(命令種別→回数), top20上位20種を含みます。

既知の制約とTipsVM×プラグイン

  • NetプラグインHTTP
    • unreachable接続不可/タイムアウト)は Result.Err(ErrorBox)
    • HTTP 404/500 は Result.Ok(Response)(アプリ側で response.status を確認)。
    • デバッグ: NYASH_NET_LOG=1 NYASH_NET_LOG_FILE=net_plugin.log
  • FileBox
    • close()Ok(Void)match Ok(_) で受けるか、戻り値を無視してよい。
  • HandleBoxRef戻り
    • TLV tag=8type_id:u32, instance_id:u32。Loaderが返り値typeに対応する fini_method_id を設定し PluginBoxV2 を構築。
    • scope_tracker がスコープ終了時に fini() を呼ぶ(メモリ安全)。
  • 大きいボディ/多ヘッダー/タイムアウト
    • 逐次拡張中。異常時の挙動は上記Result規約に従う。実行ログと --vm-stats を併用して診断。
  • 反復タイムアウト: local_tests/socket_repeated_timeouts.hakoacceptTimeout/recvTimeout の連続ケース確認
  • BoxCallデバッグ: NYASH_VM_DEBUG_BOXCALL=1 でBoxCallの受け手型・引数型・処理経路enter/fastpath/unified・結果型をstderr出力
    • 例: NYASH_VM_DEBUG_BOXCALL=1 ./target/release/nyash --backend vm local_tests/test_vm_array_getset.hako

🔧 BoxCallの統一経路Phase 9.79b

method_idスロットによるBoxCall

  • Builderが受け手型を推論できる場合、BoxCallに数値method_id(スロット)を付与。
  • 低スロットはユニバーサル予約0=toString, 1=type, 2=equals, 3=clone
  • ユーザー定義Boxは宣言時にインスタンスメソッドへスロットを4番から順に予約決定論的

VMの実行経路thunk + PIC

  • ユニバーサルスロット0..3はVMのfast-path thunkで即時処理。
    • toString/type/equals/cloneの4種は受け手VMValueから直接評価。
  • それ以外は以下の順で処理:
    1. Mono-PICモーフィックPIC直呼び: 受け手型×methodまたはmethod_idのキーでホットサイトを判定し、 InstanceBoxは関数名キャッシュを使って {Class}.{method}/{arity} を直接呼び出す(閾値=8
    2. 既存経路: InstanceBoxはMIR関数へCall、それ以外は各Boxのメソッドディスパッチへフォールバック。

環境変数(デバッグ):

NYASH_VM_DEBUG_BOXCALL=1   # BoxCallの入出力と処理経路を出力
NYASH_VM_PIC_DEBUG=1       # PICヒットのしきい値通過時にログ

今後の拡張:

  • 一般method_id(ユーザー/プラグインに対するvtableスロット→thunk直呼び。
  • PICのキャッシュ無効化型versionと多相PICへの拡張Phase 10
  • SocketBoxVM
    • 基本API: bind/listen/accept/connect/read/write/close/isServer/isConnected
    • タイムアウト: acceptTimeout(ms) は接続なしで voidrecvTimeout(ms) は空文字を返す
    • 簡易E2E: local_tests/socket_timeout_server.hakosocket_timeout_client.hako
  • Void 比較の扱いVM
    • Void は値を持たないため、Eq/Ne のみ有効。Void == Void は真、それ以外の型との == は偽(!= は真)。
    • 順序比較(<, <=, >, >=)は TypeError

E2E 実行例HTTPのResult挙動

代表ケースを tools/run_vm_stats.sh で実行できます。--vm-stats-json により命令プロファイルも取得可能です。

# 別ターミナルでサーバ起動
./target/release/nyash local_tests/http_server_statuses.hako

# クライアント(別ターミナル)
tools/run_vm_stats.sh local_tests/vm_stats_http_ok.hako vm_stats_ok.json
tools/run_vm_stats.sh local_tests/vm_stats_http_404.hako vm_stats_404.json
tools/run_vm_stats.sh local_tests/vm_stats_http_500.hako vm_stats_500.json

# 到達不能(サーバ不要)
tools/run_vm_stats.sh local_tests/vm_stats_http_err.hako vm_stats_err.json

期待されるResultモデル

  • unreachable接続不可/タイムアウト): Result.Err(ErrorBox)
  • 404/500 等のHTTPエラー: Result.Ok(Response)(アプリ側で response.status を評価)

詳細: docs/reference/architecture/mir-to-vm-mapping.mddocs/guides/examples/http_result_patterns.md を参照。