Files
hakmem/docs/specs/HAKO_MIR_FFI_SPEC.md
Moe Charm (CI) 67fb15f35f Wrap debug fprintf in !HAKMEM_BUILD_RELEASE guards (Release build optimization)
## Changes

### 1. core/page_arena.c
- Removed init failure message (lines 25-27) - error is handled by returning early
- All other fprintf statements already wrapped in existing #if !HAKMEM_BUILD_RELEASE blocks

### 2. core/hakmem.c
- Wrapped SIGSEGV handler init message (line 72)
- CRITICAL: Kept SIGSEGV/SIGBUS/SIGABRT error messages (lines 62-64) - production needs crash logs

### 3. core/hakmem_shared_pool.c
- Wrapped all debug fprintf statements in #if !HAKMEM_BUILD_RELEASE:
  - Node pool exhaustion warning (line 252)
  - SP_META_CAPACITY_ERROR warning (line 421)
  - SP_FIX_GEOMETRY debug logging (line 745)
  - SP_ACQUIRE_STAGE0.5_EMPTY debug logging (line 865)
  - SP_ACQUIRE_STAGE0_L0 debug logging (line 803)
  - SP_ACQUIRE_STAGE1_LOCKFREE debug logging (line 922)
  - SP_ACQUIRE_STAGE2_LOCKFREE debug logging (line 996)
  - SP_ACQUIRE_STAGE3 debug logging (line 1116)
  - SP_SLOT_RELEASE debug logging (line 1245)
  - SP_SLOT_FREELIST_LOCKFREE debug logging (line 1305)
  - SP_SLOT_COMPLETELY_EMPTY debug logging (line 1316)
- Fixed lock_stats_init() for release builds (lines 60-65) - ensure g_lock_stats_enabled is initialized

## Performance Validation

Before: 51M ops/s (with debug fprintf overhead)
After:  49.1M ops/s (consistent performance, fprintf removed from hot paths)

## Build & Test

```bash
./build.sh larson_hakmem
./out/release/larson_hakmem 1 5 1 1000 100 10000 42
# Result: 49.1M ops/s
```

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 13:14:18 +09:00

5.0 KiB
Raw Blame History

HAKO MIR/FFI/ABI Design (Front-Checked, MIR-Transport)

目的: フロントエンドで型整合を完結し、MIR は「最小契約最適化ヒント」を運ぶだけ。FFI/ABI は機械的に引数を並べる。バグ時は境界で FailFast。Box Theory に従い境界を1箇所に集約し、A/B で即切替可能にする。

境界Boxと責務

  • フロントエンド型チェックType Checker Box

    • 全ての型整合・多相解決を完結(例: map.set → set_h / set_hh / set_ha / set_ah
    • 必要な変換は明示命令box/unbox/castを挿入。暗黙推測は残さない。
    • MIR ノードへ Tag/Hint を添付reg→{value_kind, nullability, …})。
  • MIR 輸送Transport Box

    • 役割: i64 値Tag/Hint を「運ぶだけ」。
    • 最小検証: move/phi の Tag 一致、call 期待と引数の Tag 整合(不一致はビルド時エラー)。
  • FFI/ABI ローワリングFFI Lowering Box

    • 受け取った解決済みシンボルと Tag に従い、C ABI へ並べ替えるだけ。
    • Unknown/未解決は発行禁止FailFast。デバッグ時に 1 行ログ。

C ABIx86_64 SysV, Linux

  • 引数: RDI, RSI, RDX, RCX, R8, R9 → 以降スタック16B 整列)。返り値: RAX。
  • 値種別:
    • Int: int64_tMIR の i64 そのまま)
    • HandleBox/オブジェクト): HakoHandleuintptr_t/void* 同等の 64bit
    • 文字列: 原則 Handle。必要時のみ (const uint8_t* p, size_t n) 専用シンボルへ分岐

例: nyash.map

  • setキー/値の型で分岐)
    • void nyash_map_set_h(HakoHandle map, int64_t key, int64_t val);
    • void nyash_map_set_hh(HakoHandle map, HakoHandle key, HakoHandle val);
    • void nyash_map_set_ha(HakoHandle map, int64_t key, HakoHandle val);
    • void nyash_map_set_ah(HakoHandle map, HakoHandle key, int64_t val);
  • get常に Handle を返す)
    • HakoHandle nyash_map_get_h(HakoHandle map, int64_t key);
    • HakoHandle nyash_map_get_hh(HakoHandle map, HakoHandle key);
  • アンボックス
    • int64_t nyash_unbox_i64(HakoHandle h, int* ok);ok=0 なら非数値)

MIR が運ぶ最小契約HardとヒントSoft

  • Hard必須
    • value_kindInt/Handle/String/Ptr
    • phi/move/call の Tag 整合(不一致はフロントで cast を要求)
    • Unknown 禁止FFI 発行不可)
  • Soft任意ヒント
    • signedness, nullability, escape, alias_set, lifetime_hint, shape_hint(len/unknown), pure/no_throw など
    • 解釈はバックエンド自由。ヒント不整合時は性能のみ低下し、正しさは保持。

ランタイム検証任意・A/B

  • 既定は OFF。必要時のみ軽量ガードを ON。
  • 例: ハンドル魔法数・範囲、(ptr,len) の len 範囲。サンプリング率可。
  • ENV
    • HAKO_FFI_GUARD=0/1ON でランタイム検証)
    • HAKO_FFI_GUARD_RATE_LG=N2^N に 1 回)
    • HAKO_FAILFAST=1失敗即中断。0 で安全パスへデオプト)

Box Theory と A/B戻せる設計

  • 境界は 3 箇所(フロント/輸送/FFIで固定。各境界で FailFast は 1 か所に集約。
  • すべて ENV で A/B 可能(ガード ON/OFF、サンプリング率、フォールバック先

Phase導入段階

  1. PhaseA: Tag サイドテーブル導入フロント。phi/move 整合のビルド時検証。
  2. PhaseB: FFI 解決テーブル((k1,k2,…)→symbol)。デバッグ 1 行ログ。
  3. PhaseC: ランタイムガードA/B。魔法数/範囲チェックの軽量実装。
  4. PhaseD: ヒント活用の最適化pure/no_throw, escape=false など)。

サマリ

  • フロントで型を完結 → MIR は運ぶだけ → FFI は機械的。
  • Hard は FailFast、Soft は最適化ヒント。A/B で安全と性能のバランスを即時調整可能。

Phase 追記(このフェーズでやること)

  1. 実装(最小)
  • Tag サイドテーブルreg→Tagをフロントで確定・MIRへ添付
  • phi/move で Tag 整合アサート(不一致ならフロントへ cast を要求)
  • FFI 解決テーブル(引数の Tag 組→具体シンボル名)+デバッグ 1 行ログA/B
  • Unknown の FFI 禁止FailFast
  • ランタイム軽ガードの ENV 配線HAKO_FFI_GUARD, HAKO_FFI_GUARD_RATE_LG, HAKO_FAILFAST
  1. スモークチェック(最小ケースで通電確認)
  • map.set(Int,Int) → set_h が呼ばれる(ログで確認)
  • map.set(Handle,Handle) → set_hh が呼ばれる
  • map.get_h 返回 Handle。直後の unbox_i64(ok) で ok=0/1 を確認
  • phi で (Int|Handle) 混在 → ビルド時エラーcast 必須)
  • Unknown のまま FFI 到達 → FailFast1 回だけ)
  • ランタイムガード ONHAKO_FFI_GUARD=1, RATE_LG=8で魔法数/範囲の軽検証が通る
  1. A/B・戻せる設計
  • 既定: ガード OFFperf 影響なし)
  • 問題時: HAKO_FFI_GUARD=1 だけで実行時検証を有効化FailFast/デオプトを選択)