Phase 21.7 normalization: optimization pre-work + bench harness expansion
- Add opt-in optimizations (defaults OFF) - Ret purity verifier: NYASH_VERIFY_RET_PURITY=1 - strlen FAST enhancement for const handles - FAST_INT gate for same-BB SSA optimization - length cache for string literals in llvmlite - Expand bench harness (tools/perf/microbench.sh) - Add branch/call/stringchain/arraymap/chip8/kilo cases - Auto-calculate ratio vs C reference - Document in benchmarks/README.md - Compiler health improvements - Unify PHI insertion to insert_phi_at_head() - Add NYASH_LLVM_SKIP_BUILD=1 for build reuse - Runtime & safety enhancements - Clarify Rust/Hako ownership boundaries - Strengthen receiver localization (LocalSSA/pin/after-PHIs) - Stop excessive PluginInvoke→BoxCall rewrites - Update CURRENT_TASK.md, docs, and canaries 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
209
CURRENT_TASK.md
209
CURRENT_TASK.md
@ -1,5 +1,173 @@
|
||||
# Current Task — Phase 21.7(Normalization & Unification: Methodize Static Boxes)
|
||||
|
||||
Update (2025-11-12 — Optimization pre-work and bench harness)
|
||||
- Implemented (opt‑in, defaults OFF)
|
||||
- Ret block purity verifier: NYASH_VERIFY_RET_PURITY=1 → Return直前の副作用命令をFail‑Fast(Const/Copy/Phi/Nopのみ許可)。構造純化の安全弁として維持。
|
||||
- strlen FAST 強化: newbox(StringBox,const) だけでなく const ハンドルからの length() も即値畳み込み(NYASH_LLVM_FAST=1時)。
|
||||
- Kernel hint: nyrt_string_length に #[inline(always)] を付与(AOT呼び出しのオーバーヘッド抑制)。
|
||||
- FAST_INT ゲート: NYASH_LLVM_FAST_INT=1 で BinOp/Compare が同一ブロックSSA(vmap)を優先利用し、resolver/PHIの局所化コストを回避(文字列連結は除外)。
|
||||
- length キャッシュ(llvmlite 最低限): NYASH_LLVM_FAST=1 時、文字列リテラル由来ハンドルに対する length()/len の i64 即値を resolver.length_cache に格納し、ループ内で再利用。
|
||||
- Added
|
||||
- Bench harness 拡張(tools/perf/microbench.sh): branch/call/stringchain/arraymap/chip8/kilo を追加。各ケースは C 参照付きで ratio を自動算出。
|
||||
- Bench doc: benchmarks/README.md に一覧・実行例を追加。
|
||||
- Preliminary results(LLVM/EXE, ノイズ抑制: NYASH_SKIP_TOML_ENV=1 NYASH_DISABLE_PLUGINS=1)
|
||||
- 良好: call / stringchain / kilo → ratio < 100%(Nyash側が軽い)
|
||||
- 要改善: branch / arraymap / chip8 → ratio ≈ 200%(Cの約1/2速度)
|
||||
|
||||
Compiler health(E0308対応)
|
||||
- PHI 挿入のコールサイトを監査し、`insert_phi_at_head(&mut MirFunction, ...)` へ統一(`current_function.as_mut()` 経由で渡す)。`cargo check` は通過済み。
|
||||
- `tools/ny_mir_builder.sh --emit exe` 実行時にワークスペース再ビルドが走る環境では、必要に応じて `NYASH_LLVM_SKIP_BUILD=1` を指定し、既存の `ny-llvmc` / `nyash_kernel` ビルド成果物を用いる運用を併記。
|
||||
- Next actions(AOT集中; 既定OFFのまま段階適用)
|
||||
1) ループ不変の簡易ホイスティング(strlen/比較/分母mod など)
|
||||
2) FAST_INT の適用範囲精緻化(不要cast/extendの抑制、CFG保存のまま)
|
||||
3) array/map のホットパス検討(AOT経路のみ・診断OFF)
|
||||
4) 再ベンチ(branch/arraymap/chip8 を再測)、目標: ratio ≤ 125%(Cの8割)
|
||||
5) 既定OFFで挙動不変・Ret純化ガード緑維持・小差分リバーシブルを堅持
|
||||
|
||||
Toggles(再掲)
|
||||
- NYASH_LLVM_FAST=1 … strlen FAST + literal length キャッシュ
|
||||
- NYASH_LLVM_FAST_INT=1 … i64 ホットパス(同一BB SSA 優先)
|
||||
- NYASH_VERIFY_RET_PURITY=1 … Ret 純化ガード(開発ガード)
|
||||
- NYASH_LLVM_SKIP_BUILD=1 … ny_mir_builder.sh の再ビルド抑止(既存バイナリ再利用)
|
||||
- NYASH_MIR_DEV_IDEMP=1 … MIR normalize/dev 用の再実行安定化(idempotence)メタ。既定OFF(診断専用)
|
||||
- HAKO_MIR_NORMALIZE_PRINT=1 … AotPrep(.hako) 側で print→externcall(env.console.log) を正規化(CFG不変・既定OFF)
|
||||
- HAKO_MIR_NORMALIZE_REF=1 … AotPrep(.hako) 側で ref_get/ref_set→boxcall(getField/setField) を正規化(CFG不変・既定OFF)
|
||||
- HAKO_SILENT_TAGS=0|1 … v2ランナーのタグ静音トグル(1=静音:既定、0=生ログ)
|
||||
|
||||
|
||||
Wrap‑up (this session)
|
||||
- Rust/Hako ownership clarified(docs/development/normalization/ownership.md)。Hako=意味論正規化、Rust=構造/安全。
|
||||
- Runtime autoload for using.dylib(guarded)を Runner 初期化に集約。箱名は nyash_box.toml から推論して登録。
|
||||
- Builder/VM safety: 受信ローカライズを強化(LocalSSA/pin/after‑PHIs/tail)。未定義受信は同一BBの直近 NewBox<Box> で構造回復(dev 安全弁)に限定。
|
||||
- PluginInvoke→BoxCall の過剰な書換えを停止(意味論は Hako 側の methodize に集約)。
|
||||
- カナリア:
|
||||
- phase217_methodize_canary.sh → PASS(rc=5)。
|
||||
- phase217_methodize_json_canary.sh → v1 + mir_call present(Method が優先、Global は経過容認)。
|
||||
- phase217_methodize_json_strict.sh を追加(selfhost‑only 仕上げ用ゲート、現状は Stage‑B child パース修正が必要)。
|
||||
|
||||
## Phase 21.5 — Optimization Checklist(進行管理)
|
||||
|
||||
- [x] パス分割(AotPrep: StrlenFold / LoopHoist / ConstDedup / CollectionsHot / BinopCSE)
|
||||
- [x] CollectionsHot: Array/Map の boxcall→externcall(既定OFF・トグル)
|
||||
- [x] Map key モード導入(`NYASH_AOT_MAP_KEY_MODE={h|i64|hh|auto}`)
|
||||
- [x] LoopHoist v1: compare/mod/div 右辺 const の前出し(参照 const を先頭へ)
|
||||
- [x] BinopCSE v1: `+/*` の同一式を再利用、`copy` で伝播
|
||||
- [x] VERIFY ガード常時ON(`NYASH_VERIFY_RET_PURITY=1`)で測定
|
||||
- [x] ベンチ新規(`linidx`/`maplin`)追加・実測を README に反映
|
||||
- [x] LoopHoist v2: `+/*` 右項 const の連鎖前出し、fix‑point(≤3周)の安全適用(定数 binop 折畳み+hoist 実装)
|
||||
- [x] BinopCSE v2: 線形 `i*n` の共通化強化(copy 連鎖の正規化・左右交換可の正規化)
|
||||
- [x] CollectionsHot v2: Array/Map index/key の式キー共有(同一ブロック短窓で get/set の a0 を統一)
|
||||
- [x] Map auto 精緻化: `_is_const_or_linear` の再帰判定強化(copy 追跡+div/rem の定数片を線形扱い)
|
||||
- [x] Rust normalize.rs の借用修正(E0499/E0502解消)+ dev idempotence メタ追加(既定OFF)
|
||||
- [x] 正規化の .hako 化(新箱でモジュール化):NormalizePrint / NormalizeRef を AotPrep から opt-in で呼び出し
|
||||
- [ ] Idempotence: 置換済みマーク(devメタ)で再実行の結果不変を担保
|
||||
- [ ] ベンチ更新: `arraymap`/`matmul`/`sieve`/`linidx`/`maplin` EXE 比率 ≤ 125%(arraymap/matmul優先)
|
||||
|
||||
### 21.5 引き継ぎメモ(ベンチ&観測)
|
||||
- 新規トグル/修正
|
||||
- `NYASH_LLVM_DUMP_MIR_IN=/tmp/xxx.json`(AOT 入力MIRダンプ)
|
||||
- dump_mir.sh: provider/selfhost-first + min fallback で実MIRダンプを安定化
|
||||
- microbench: `PERF_USE_PROVIDER=1` で jsonfrag 強制を解除(実MIRでの突合せ用)
|
||||
- ベンチ現状(EXE, C=100%)
|
||||
- arraymap: 150–300%(分散あり) / matmul: 300% / sieve: 200% / linidx: 100% / maplin: 200%
|
||||
- 次のアクション
|
||||
1) arraymap/matmul の実MIR(provider or `NYASH_LLVM_DUMP_MIR_IN`)で index SSA 共有の崩れを特定
|
||||
2) CollectionsHot v2.1: 同一ブロック短窓 get→set で a0 の一致を強制(式キー統一の取りこぼし追加)
|
||||
3) BinopCSE 小窓 fix‑point 拡張(隣接ブロックまでの `i*n+k` 共有; 制御不変・既定OFF)
|
||||
4) 再ベンチ(arraymap/matmul/maplin)→ `benchmarks/README.md` に 日付/トグル/ratio ≤ 125% を追記
|
||||
5) provider emit の失敗パターンを継続調査(emit ラッパの fallback/guard を追加調整)
|
||||
|
||||
Decisions
|
||||
- 既定挙動は変更しない(dev では methodize トグルON、CI/ユーザ既定は従来維持)。
|
||||
- Rust 層は正規化を持たず、構造のみ(SSA/PHI/LocalSSA/安全弁)。Hako が mir_call(Method) のSSOT。
|
||||
|
||||
Rust normalize.rs sunset plan(記録)
|
||||
- 目的: normalize.rs の責務を .hako 側へ移し、Rust 側は既定OFF→撤去へ。
|
||||
- 段階:
|
||||
- 1) dev カナリア期間は `HAKO_MIR_NORMALIZE_*`(PRINT/REF/ARRAY)を opt-in で運用(既定OFF)。
|
||||
- 2) AotPrep 経由の normalize が十分に安定後、dev/quick で既定ONへ昇格(CI は段階移行)。
|
||||
- 3) Rust 側 normalize は env で明示 ON のみ許可(互換ガードを残す)。
|
||||
- 4) 既定ON 状態で 2 週安定を確認後、Rust normalize のビルド配線を外し、最終撤去。
|
||||
- 付随: 新規/更新トグルは env 一覧へ追記し、昇格時にデフォルト化→古いトグルは段階的に非推奨化とする。
|
||||
|
||||
Follow‑ups (carried to backlog)
|
||||
- Stage‑B child の "Unexpected token FN" 修正(selfhost‑first/strict ゲート用)。
|
||||
- Provider 出力の callee を Method へ寄せ、Global 経過容認を段階縮小。
|
||||
- core_bridge の methodize ブリッジは bring‑up 用。Hako 既定化後に撤去。
|
||||
|
||||
|
||||
# Next Active Task — Phase 21.16(Pre‑Optimization / 最適化前フェーズへ戻す)
|
||||
|
||||
Intent
|
||||
- 正規化の骨格が揃った段階で、最適化前の安定化に戻す(意味論は不変、構造/観測の強化)。
|
||||
|
||||
Scope(当面の作業)
|
||||
1) Optimizer 前段の安定化(構造のみ)
|
||||
- normalize_legacy/ref_field_access は構造変換の範囲に留める(意味論を変えない)。
|
||||
- NYASH_MIR_DISABLE_OPT/HAKO_MIR_DISABLE_OPT で最適化全休のゲートを尊重(既存)。
|
||||
2) Baseline/観測
|
||||
- quick/integration の rc/出力をゴールデン更新(mir_call 既定はまだOFF)。
|
||||
- crate_exec タイムボックスを EXE テストへ段階横展開。
|
||||
- プラグイン parity の軽量観測(autoload ガード有効時)。
|
||||
3) テスト整備
|
||||
- 受信未定義の負テスト追加(Builder で防止)。dev 安全弁を将来的にOFFにできる状態を作る。
|
||||
- v1 + unified の canary は dev のみ strict を維持(CI は現状どおり)。
|
||||
|
||||
Exit criteria(21.16)
|
||||
- Optimizer OFF でも quick/integration/plugins が安定緑。
|
||||
- 受信ローカライズの穴が負テストで検知可能(dev 安全弁に依存しない)。
|
||||
- v1/unified は dev プロファイルで常時確認可能(既存トグルで担保)。
|
||||
|
||||
Handoff Summary (ready for restart)
|
||||
- Delegate v1 fixed (provider‑first): tools/hakorune_emit_mir.sh now prefers env.mirbuilder.emit to emit MIR(JSON v1). Legacy CLI converter kept as fallback with NYASH_JSON_SCHEMA_V1=1/NYASH_MIR_UNIFIED_CALL=1.
|
||||
- Selfhost‑first stabilized for mini cases: HAKO_SELFHOST_TRY_MIN=1 in dev profile; min runner (BuilderRunnerMinBox.run) is used when builder fails.
|
||||
- Methodize canaries:
|
||||
- phase217_methodize_canary.sh → compile‑run rc=5 PASS(semantics)
|
||||
- phase217_methodize_json_canary.sh → schema_version present + mir_call present(Method preferred; Global tolerated for now)
|
||||
- Dev one‑gun toggles (enable_mirbuilder_dev_env.sh): HAKO_STAGEB_FUNC_SCAN=1, HAKO_MIR_BUILDER_FUNCS=1, HAKO_MIR_BUILDER_CALL_RESOLVE=1, NYASH_JSON_SCHEMA_V1=1, NYASH_MIR_UNIFIED_CALL=1, HAKO_SELFHOST_TRY_MIN=1.
|
||||
|
||||
Next Steps (post‑restart)
|
||||
1) Selfhost‑first child parse fix(Stage‑B): resolve the known “Unexpected token FN” in compiler_stageb chain; target [builder/selfhost‑first:ok] without min fallback.
|
||||
2) Provider output callee finishing: prefer Method callee so JSON canary asserts Method strictly (now Global allowed temporarily).
|
||||
3) Consolidate remaining legacy converter usage to provider where possible; keep defaults unchanged.
|
||||
4) Docs: 21.7 checklist updated; core_bridge methodize remains diagnostic‑only (OFF) with a removal plan once Hako methodize is default.
|
||||
|
||||
|
||||
# New Active Task — Phase 21.6(Dual‑Emit Parity & C‑line Readiness)
|
||||
|
||||
Intent
|
||||
- Provider(Rust)と Selfhost(Hako)で同一の MIR(JSON) を出力できることを確認し、生成時間を計測・比較する。AOT(ny‑llvmc/crate)も O0 既定で安定させる。
|
||||
|
||||
What’s done (this session)
|
||||
- Perf ツール追加:
|
||||
- MIR emit bench: `tools/perf/bench_hakorune_emit_mir.sh`
|
||||
- AOT bench: `tools/perf/bench_ny_mir_builder.sh`
|
||||
- 構造比較: `tools/perf/compare_mir_json.sh`
|
||||
- Dual emit + 比較 + ベンチ: `tools/perf/dual_emit_compare.sh`
|
||||
- Docs 整備:
|
||||
- `docs/guides/perf/benchmarks.md`(手順/トグル)
|
||||
- README/README.ja にパフォーマンス導線を追記
|
||||
- `docs/ENV_VARS.md` にベンチ関連のトグルを追加
|
||||
- 小最適化(意味論不変):
|
||||
- Builder の不要 clone / finalize 二重呼び出し削減
|
||||
- VM console 出力の to_string の枝刈り(String/StringBox/Null 先出し)
|
||||
- VM 受信未定義の負テストを 3 本追加(Array/Map/String)。fail‑fast を監視
|
||||
|
||||
Known issue / Action
|
||||
- Provider 経路(tools/hakorune_emit_mir.sh の provider‑first)が一部環境で `Program→MIR delegate failed` になることがある。
|
||||
- 原因: Stage‑B 実行の stdout にログが混在し JSON 抽出が空になるケース。
|
||||
- 対策(次実装): ラッパを tmp 経由の CLI 変換(`--program-json-to-mir`)へフォールバックさせる安全化。selfhost‑first も明示トグルで維持。
|
||||
|
||||
Plan (next after restart)
|
||||
1) tools/hakorune_emit_mir.sh を安全化(Stage‑B→tmp→CLI 変換フォールバック)。stderr/JSON 分離を強化
|
||||
2) 代表 4 ケース(json_pp / json_query_min / json_lint / json_query)で dual‑emit を 5 回実行し、21.6 表に p50/Parity を記入
|
||||
3) Parity 不一致はカテゴリ化(callee 種別/順序/PHI/メタ)して修正元を特定(provider か selfhost)
|
||||
4) AOT(ny‑llvmc)O0 の 3 回ベンチを取得、必要なら O1 スポットも取得
|
||||
|
||||
Tracking
|
||||
- 記録台帳: `docs/development/roadmap/phases/phase-21.6/README.md` の表へ随時追記(チェックボックス方式)
|
||||
|
||||
|
||||
Phase 21.6 wrap-up
|
||||
- Parser(Stage‑B) ループJSONの保守フォールバックで壊れ形のみ復元(正常形は素通り)
|
||||
- 代表E2E(return/binop/loop/call)PASS(call は関数化: "Main.add" → Global 関数呼び出し)
|
||||
@ -131,9 +299,44 @@ Notes(ライン確認)
|
||||
- Helper: `tools/hakorune_emit_mir.sh`(Stage‑B→MIR)、`tools/ny_mir_builder.sh --emit exe`(crate で obj/exe)
|
||||
|
||||
- Done (recent)
|
||||
- EXE canaries hardened(enable_exe_dev_env 適用・検証ON・代表は FAIL 基準へ昇格)
|
||||
- VM runtime counters(`NYASH_VM_STATS=1`)
|
||||
- microbench `--exe` 実装(ビルド1回→EXEをRUNS回実行)。現状、loop/strlen の一般形は crate 未対応で EXE 失敗 → 上記 1)/2) で解消予定。
|
||||
- EXE canaries hardened(enable_exe_dev_env 適用・検証ON・代表は FAIL 基準へ昇格)
|
||||
- VM runtime counters(`NYASH_VM_STATS=1`)
|
||||
- microbench `--exe` 実装(ビルド1回→EXEをRUNS回実行)。現状、loop/strlen の一般形は crate 未対応で EXE 失敗 → 上記 1)/2) で解消予定。
|
||||
|
||||
2025‑11‑12 Updates(PHI grouping fix, ret‑after guards, provider hooks)
|
||||
- LLVM Python backend(llvmlite harness/crate 経由)
|
||||
- Return 合成 PHI を常にブロック先頭に配置(PHI グルーピング違反の根治)。
|
||||
- lowering 入口(boxcall/mir_call/safepoint)で terminator 後の誤挿入を防止(継続BBへ移動)。
|
||||
- builder 側でブロック命令列は最初の terminator(ret/branch/jump)で打ち切る。
|
||||
- JsonFrag 正規化・純化(dev)
|
||||
- purify=1 で newbox/boxcall/externcall/mir_call を除去、ret 以降を打ち切り。
|
||||
- provider-first フック(dev)
|
||||
- HAKO_MIR_NORMALIZE_PROVIDER=1 で provider 出力 MIR にも正規化を適用可能。
|
||||
- HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG=1 を provider-first にも適用(最小ループ MIR を直返し)。
|
||||
|
||||
Verified
|
||||
- selfhost-first + JsonFrag 正規化+purify: llvmlite=OK / ny‑llvmc=OK(EXE生成)
|
||||
- provider-first + FORCE_JSONFRAG: ny‑llvmc=OK(EXE生成)
|
||||
|
||||
Open
|
||||
- provider-first の通常出力に対する純化強化(ret ブロックの副作用禁止を徹底)。
|
||||
- strlen(FAST) の適用強化(resolver マーク補強 → IR に nyrt_string_length を反映)。
|
||||
|
||||
- Rust→.hako Normalize 移行計画(Self‑Host First / Freeze準拠)
|
||||
- 方針
|
||||
- 正規化/置換系は Rust 側から .hako(AotPrep/MirBuilder 直下の新規箱)へ段階移行する。
|
||||
- Rust 層は最小シーム+安全ガード(互換維持・借用修正・診断)に限定。既定挙動は不変。
|
||||
- 現状
|
||||
- 実装済み(opt‑in、既定OFF): NormalizePrintBox(print→externcall)、NormalizeRefBox(ref_get/ref_set→boxcall)。
|
||||
- Rust 側 normalize.rs は借用修正のみ。dev 用 idempotence トグル(NYASH_MIR_DEV_IDEMP=1)を追加(既定OFF)。
|
||||
- これから(段階)
|
||||
1) .hako 正規化のカナリア整備(出力形状トークン検証+VM/EXE RC パリティ)。
|
||||
2) Rust 側の同等パスは「既定OFF」を明文化し、.hako 側が有効な場合は二重適用を避ける運用に統一(最終的に Rust 側の normalize はOFF運用)。
|
||||
3) 代表ケースが緑になった段階で、.hako 側をデフォルト化(dev/bench ラッパでON)。
|
||||
4) 安定期間後、Rust 側の当該パスを撤去(環境変数は deprecate → 警告 → 削除の順)。
|
||||
- 環境変数の扱い(増えたトグルの将来)
|
||||
- いまは opt‑in(既定OFF)。デフォルト化タイミングで .hako 側トグルはON に寄せ、Rust 側の旧トグルは非推奨化。
|
||||
- 最終的に Rust 側トグルは削除(ドキュメントも更新)。.hako 側は必要最小のみ残す。
|
||||
|
||||
- Next (actionable)
|
||||
- Implement loop JSONFrag purification (no MapBox/newbox) and add canary
|
||||
|
||||
Reference in New Issue
Block a user