# Geminiへのリファクタリング実装指示書 Version: 1.0 (2025-12-03) Status: 実装開始準備完了 --- ## 📋 背景 TLS_SLL_HDR_RESET の根本原因調査が完了しました。 **結論**: - **Issue A** (ヘッダー復元漏れ): ✅ **修正済み** (4つのコミット) - **Issue B** (アラインメント違反): ⚠️ **現在防御中**、Phase 2で根治予定 Gemini の最終報告書 (`docs/tls_sll_hdr_reset_final_report.md`) で、**sh8bench がmalloc返却値に +1 を加えて使用している**ことが数学的に証明されました。 --- ## 🎯 Phase 1 実装目標 **目的**: Box パターンに基づいた Tiny Allocator のロジック集約 **期間**: 段階的(A/B テスト可能な形で) **リスク**: 低(既存の防御機構は継続) --- ## 📝 実装タスク(優先度順) ### Task 1.1: `tiny_layout_box.h` 作成 ⭐⭐⭐ (CRITICAL) **目的**: クラスサイズ・ヘッダーオフセットの定義を一箇所に集約 **場所**: `core/box/tiny_layout_box.h` (新規作成) **内容**: ```c /** * @file tiny_layout_box.h * @brief Box: Tiny Allocator Layout Definitions * * MISSION: Single source of truth for class size and header layout * * Current Design (Phase E1-CORRECT): * - All classes (0-7) have 1-byte header * - User pointer = base + 1 for classes 0-6, base + 0 for class 7 * (Note: Class 7 is headerless in practice but marked for consistency) * - No external code should hardcode offsets */ #ifndef TINY_LAYOUT_BOX_H #define TINY_LAYOUT_BOX_H #include // Define all class-specific layout parameters // Current: Defined in g_tiny_class_sizes[8] in hakmem_tiny.c // TODO: Move to this file and make accessible here // Example macro (to be filled in): // #define TINY_CLASS_SIZE(cls) g_tiny_class_sizes[cls] // #define TINY_HEADER_SIZE 1 // #define TINY_USER_OFFSET(cls) ((cls) == 7 ? 0 : 1) // Validation macros static inline int tiny_class_is_valid(int class_idx) { return class_idx >= 0 && class_idx < 8; } static inline size_t tiny_class_stride(int class_idx) { extern const size_t g_tiny_class_sizes[8]; return tiny_class_is_valid(class_idx) ? g_tiny_class_sizes[class_idx] : 0; } #endif // TINY_LAYOUT_BOX_H ``` **提出物**: - [ ] `core/box/tiny_layout_box.h` 完成 - [ ] `tiny_nextptr.h` がこれを `#include` するように修正 - [ ] テスト: `tiny_class_stride()` が正しい値を返すか確認 --- ### Task 1.2: `tiny_nextptr.h` 監査 ⭐⭐⭐ (CRITICAL) **目的**: 直接的な `+1` 計算を排除し、レイアウト Box に依存させる **確認対象**: ```c // 現在のコード例: size_t off = tiny_next_off(class_idx); // ✅ OK (Box化済み) *(uint8_t*)base = HEADER_MAGIC | (class_idx & HEADER_CLASS_MASK); // ⚠️ 要確認 ``` **チェックリスト**: - [ ] `tiny_next_off()`: Box 化済み (確認: `core/tiny_nextptr.h:51-62`) - [ ] `tiny_next_load()`: Box 化済み (確認: `core/tiny_nextptr.h:66-87`) - [ ] `tiny_next_store()`: Box 化済み (確認: `core/tiny_nextptr.h:95-123`) - [ ] ヘッダー関連マジック値: `tiny_header_box.h` に一元化されているか確認 - [ ] 直接的な `(void*)((char*)base + 1)` 計算: 全箇所を `ptr_conversion_box.h` に置き換え **提出物**: - [ ] 監査結果レポート(`docs/tiny_nextptr_audit.md`) - [ ] 修正が必要な箇所のリスト - [ ] 修正済みファイル群 --- ### Task 1.3: `hakmem_tiny.c` のポインタ型一貫性 ⭐⭐ (HIGH) **目的**: `hakmem_tiny.c` で `hak_base_ptr_t` / `hak_user_ptr_t` を正しく使い分ける **確認対象**: ```c // 変換すべきパターン: void* p = ...; // ⚠️ 型不明確 void* user = (char*)base + 1; // ❌ 直接計算 → ptr_conversion_box 使用 void* base_p = (char*)user - 1; // ❌ 直接計算 → ptr_conversion_box 使用 ``` **修正方法**: ```c // 修正後: hak_user_ptr_t user = ptr_base_to_user(base, class_idx); // ptr_conversion_box.h hak_base_ptr_t base = ptr_user_to_base(user, class_idx); // ptr_conversion_box.h ``` **チェックリスト**: - [ ] `hakmem_tiny.c` で `hak_base_ptr_t` が使用されている箇所: リスト化 - [ ] `hakmem_tiny.c` で `hak_user_ptr_t` が使用されている箇所: リスト化 - [ ] 型不一致の警告が出ないことを確認(コンパイルテスト) **提出物**: - [ ] 修正箇所のリスト - [ ] 修正済み `hakmem_tiny.c` - [ ] コンパイル結果(警告なし) --- ### Task 1.4: Box 間の型安全性テスト ⭐⭐ (MEDIUM) **目的**: `ptr_type_box.h` の Phantom Types が実際に型エラーを検出するか確認 **テスト内容**: ```c // Debug build で以下がコンパイルエラーになることを確認: hak_base_ptr_t base = HAK_BASE_FROM_RAW(ptr); hak_user_ptr_t user = base; // ❌ Type mismatch (Debug build) int cmp = hak_base_eq(base, user); // ❌ Type mismatch (Debug build) ``` **ビルドコマンド**: ```bash cd /mnt/workdisk/public_share/hakmem # Debug build (Phantom Types enabled) make clean make shared -j8 EXTRA_CFLAGS="-g -DHAKMEM_DEBUG_VERBOSE=1" # 型エラーが出ることを確認 # 出なければ: HAKMEM_TINY_PTR_PHANTOM のデフォルト値を見直す ``` **提出物**: - [ ] テスト結果レポート - [ ] コンパイル log (エラーメッセージ含む) --- ## 📊 Phase 2 準備 (参考) **当面は実装不要** ですが、Phase 1 完了後に以下を検討してください: ### Phase 2.1: Headerless Layout Design 現在の `user = base + 1` 設計を `user = base + 0` に変更する場合: - **メタデータ回復**: `free()` で class_idx をどうやって判定するか - 案A: SuperSlab Registry (現在実装済み) - 案B: Bitmap (パフォーマンス影響検討必要) - 案C: Out-of-line header (外部テーブル) - **パフォーマンス影響**: - ヘッダー読み込みコスト削減: 利得 - SuperSlab lookup 増加: 負荷増加 - 総合的にどちらが利得か: ベンチマーク必要 --- ## 🧪 テスト計画 ### Unit Tests ```bash # Phase 1.1: tiny_layout_box make test -j8 FILTER="tiny_layout" # Phase 1.2: tiny_nextptr make test -j8 FILTER="tiny_nextptr" # Phase 1.3: hakmem_tiny make test -j8 FILTER="hakmem_tiny" ``` ### Integration Tests ```bash # sh8bench (既存の動作確認) LD_PRELOAD=./libhakmem.so ./mimalloc-bench/out/bench/sh8bench 2>&1 | \ grep -E "TLS_SLL_HDR_RESET|Total" # cfrac, larson (非推奨な挙動が出ないか) LD_PRELOAD=./libhakmem.so ./mimalloc-bench/out/bench/cfrac 2>&1 | grep -i error LD_PRELOAD=./libhakmem.so ./mimalloc-bench/out/bench/larson 8 2>&1 | grep -i error ``` --- ## 📝 実装時の注意 ### ✅ すべき事 1. **Box パターン厳守**: 各 Box は単一責任を持つ 2. **A/B テスト機能**: 環境変数で旧動作に戻せるようにする 3. **詳細ログ**: デバッグフラグで詳細な実行ログを出力可能に 4. **型安全性**: Debug build では Phantom Types で型チェック ### ❌ してはいけない事 1. **直接的なポインタ計算**: `(char*)ptr + 1` は Box API 経由に 2. **散らばったオフセット定義**: `tiny_layout_box.h` に集約 3. **グローバル変数の氾濫**: 既存のグローバルを活用 4. **無関係な最適化**: 本タスクに集中 --- ## 📞 進捗報告形式 各タスク完了時に以下の形式で報告してください: ``` ## Task [番号] 完了レポート **実装内容**: - 作成/修正ファイル: ... - 主な変更: ... **テスト結果**: - ビルド: ✅ 成功 / ❌ 失敗 - 既存テスト: ✅ 全て通過 / ❌ XX件失敗 **備考**: - 予期しない課題があれば記述 - Phase 2 への提案があれば記述 **次のステップ**: - Task [次の番号] へ進む ``` --- ## 🎁 完了後の評価基準 | 基準 | 期待値 | |------|--------| | **コード品質** | Box 理論に完全準拠、型安全性確保 | | **テスト** | sh8bench/cfrac/larson で回帰なし | | **ドキュメント** | Phase 1 実装の詳細説明あり | | **パフォーマンス** | ≤ 5% の低下に抑制 | --- ## 参考資料 - `docs/REFACTOR_PLAN_GEMINI_ENHANCED.md` - マスタープラン - `docs/tls_sll_hdr_reset_final_report.md` - 根本原因分析 - `core/box/ptr_type_box.h` - Phantom Types 実装例 - `core/box/ptr_conversion_box.h` - ポインタ変換 Box - `core/tiny_nextptr.h` - Next Pointer Box (既実装の参考) --- よろしくお願いします!🙏 Gemini の努力に感謝。Phase 1 の成功が、hakmem をより堅牢で標準準拠なアロケータへ進化させます!