# 機能設計書 3-mrb_state管理

## 概要

本ドキュメントは、mrubyインタプリタ状態（mrb_state）の生成（mrb_open）・破棄（mrb_close）を管理する機能の設計を記述する。

### 本機能の処理概要

mrb_state管理はmrubyインタプリタの生成から破棄までのライフサイクルを管理する。`mrb_open`で新しいインタプリタインスタンスを生成し、GC初期化・コア初期化・gem初期化を順次実行する。`mrb_close`でインタプリタを破棄し、全リソースを解放する。

**業務上の目的・背景**：mrubyは複数のインタプリタインスタンスを同時に実行できる設計であり、各インスタンスの状態を独立して管理する必要がある。mrb_state構造体はインタプリタの全状態（クラス階層、シンボルテーブル、GC状態、VMコンテキスト等）を保持する中心的な存在である。

**機能の利用シーン**：アプリケーション起動時の`mrb_open()`呼び出し、組み込みシステムでのインタプリタ初期化・終了処理、テストフレームワークでのインスタンス生成・破棄。

**主要な処理内容**：
1. mrb_state構造体のメモリ割り当てとゼロ初期化
2. GCの初期化（`mrb_gc_init`）
3. VMコンテキスト（mrb_context）の生成
4. コアモジュールの初期化（`mrb_init_core`）
5. gem初期化（`mrb_init_mrbgems`）
6. 終了処理コールバック（atexit_stack）の管理
7. 全リソースの解放（`mrb_close`）

**関連システム・外部連携**：GC初期化、コア初期化（init.c）、gem初期化、irep管理、メモリアロケータ。

**権限による制御**：なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングにデータなし |

## 機能種別

初期化・終了処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | mrb_openはパラメータなし | - |
| mrb | mrb_state* | Yes | mrb_closeの対象（破棄時） | NULLチェック |
| f | mrb_atexit_func | Yes | atexit登録関数 | - |

### 入力データソース

なし（新規インスタンス生成）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| mrb_state* | mrb_state* | mrb_openの戻り値（初期化されたインタプリタ状態） |
| top_self | mrb_value | トップレベルオブジェクト（mrb_top_self） |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
1. mrb_open()
   ├─ mrb_open_core()
   │   ├─ mrb_basic_alloc_funcでmrb_state構造体割り当て
   │   ├─ ゼロ初期化、bootstrapping=TRUE設定
   │   ├─ mrb_core_init_protect()で保護付き初期化
   │   │   ├─ mrb_gc_init() - GC初期化
   │   │   ├─ mrb_contextの割り当て・初期化
   │   │   └─ mrb_init_core() - コアモジュール初期化
   │   ├─ mrb_method_cache_clear()
   │   └─ bootstrapping=FALSE設定
   └─ mrb_init_mrbgems() - gem初期化
2. mrb_close()
   ├─ mrb_protect_atexit() - atexit関数の実行
   ├─ mrb_gc_free_gv() - グローバル変数解放
   ├─ mrb_gc_destroy() - GC破棄
   ├─ mrb_free_context() - VMコンテキスト解放
   ├─ mrb_free_symtbl() - シンボルテーブル解放
   ├─ ROM MTラッパーの解放
   └─ mrb_free(mrb) - mrb_state自身の解放
```

### フローチャート

```mermaid
flowchart TD
    A[mrb_open] --> B[mrb_open_core]
    B --> C[mrb_state メモリ割り当て]
    C --> D{成功?}
    D -->|No| E[NULL返却]
    D -->|Yes| F[ゼロ初期化]
    F --> G[mrb_gc_init]
    G --> H[mrb_context生成]
    H --> I[mrb_init_core]
    I --> J{例外?}
    J -->|Yes| K[exc付きmrb返却]
    J -->|No| L[mrb_init_mrbgems]
    L --> M[初期化完了mrb返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 初期化保護 | mrb_core_init_protectにより初期化中の例外を捕捉し、exc付きmrbを返却 | mrb_open時 |
| BR-02 | atexit上限 | MRB_FIXED_STATE_ATEXIT_STACK_SIZE（デフォルト5）個まで登録可能 | 固定スタック時 |
| BR-03 | NULLチェック | mrb_closeはNULLを渡しても安全 | mrb_close呼び出し時 |

### 計算ロジック

特になし。

## データベース操作仕様

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NULL返却 | メモリ割り当て失敗 | mrb_basic_alloc_funcがNULL返却 | メモリ増加 |
| exc設定 | 初期化例外 | mrb_init_core/mrb_init_mrbgemsで例外発生 | mrb->excを確認 |
| RuntimeError | atexit上限超過 | 固定スタック超過 | atexit登録数の削減 |

### リトライ仕様

リトライ機構なし。

## トランザクション仕様

該当なし

## パフォーマンス要件

特になし。初期化処理は一度だけ実行される。

## セキュリティ考慮事項

- mrb_state構造体のゼロ初期化による未初期化メモリの防止
- 初期化失敗時のエラー情報（mrb->exc）による安全な失敗通知

## 備考

- state.cは248行の比較的小規模なファイル
- irep管理（mrb_irep_incref/decref/free）もstate.cに実装されている
- `mrb_open_core`はgem未ロードの最小構成でインタプリタを生成する

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mruby.h | `include/mruby.h` | mrb_state構造体（263-340行目）: 全フィールドの役割 |
| 1-2 | mruby.h | `include/mruby.h` | mrb_context構造体（196-207行目）: VMコンテキスト |
| 1-3 | mruby.h | `include/mruby.h` | mrb_atexit_func型定義（248行目） |

**読解のコツ**: mrb_stateはmrubyの全状態を保持する巨大な構造体。`c`（現在コンテキスト）と`root_c`（ルートコンテキスト）の関係に注意。

#### Step 2: インタプリタ生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | state.c | `src/state.c` | mrb_open_core()（39-61行目）: 最小構成での初期化 |
| 2-2 | state.c | `src/state.c` | init_gc_and_core()（25-36行目）: GC・コンテキスト・コア初期化 |
| 2-3 | state.c | `src/state.c` | mrb_open()（72-90行目）: gem含む完全初期化 |

**主要処理フロー**:
- **45-46行目**: mrb_basic_alloc_funcでmrb_state割り当て、NULLチェック
- **48-50行目**: ゼロ初期化、atexit_stack_len=0、bootstrapping=TRUE
- **52行目**: mrb_core_init_protectで保護付き初期化
- **57-58行目**: メソッドキャッシュクリア、bootstrapping=FALSE

#### Step 3: インタプリタ破棄を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | state.c | `src/state.c` | mrb_close()（179-203行目）: リソース解放の順序 |
| 3-2 | state.c | `src/state.c` | mrb_free_context()（167-174行目）: コンテキスト解放 |
| 3-3 | state.c | `src/state.c` | mrb_state_atexit()（227-247行目）: atexit関数登録 |

**主要処理フロー**:
- **182行目**: NULLガード
- **183行目**: mrb_protect_atexit実行
- **186-189行目**: グローバル変数→GC→コンテキスト→シンボルテーブルの順で解放
- **192-200行目**: ROM MTラッパーリストの解放
- **202行目**: mrb_state自身の解放

### プログラム呼び出し階層図

```
mrb_open()
    │
    ├─ mrb_open_core()
    │      │
    │      ├─ mrb_basic_alloc_func() ─── mrb_state割り当て
    │      │
    │      └─ mrb_core_init_protect()
    │             └─ init_gc_and_core()
    │                    ├─ mrb_gc_init() ─── GC初期化
    │                    ├─ mrb_malloc() ─── mrb_context割り当て
    │                    └─ mrb_init_core() ─── コア初期化
    │
    └─ mrb_init_mrbgems() ─── gem初期化

mrb_close()
    │
    ├─ mrb_protect_atexit() ─── 登録関数実行
    ├─ mrb_gc_free_gv() ─── グローバル変数解放
    ├─ mrb_gc_destroy() ─── GC破棄
    ├─ mrb_free_context() ─── コンテキスト解放
    ├─ mrb_free_symtbl() ─── シンボルテーブル解放
    └─ mrb_free(mrb) ─── mrb_state解放
```

### データフロー図

```
[入力]                     [処理]                         [出力]

(なし) ──────────────────▶ mrb_open()                   ──▶ mrb_state* (初期化済み)
                           │
mrb_state* ──────────────▶ mrb_close()                  ──▶ (全リソース解放)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| state.c | `src/state.c` | ソース | mrb_state生成・破棄、irep管理 |
| init.c | `src/init.c` | ソース | mrb_init_core()によるコアモジュール初期化 |
| mruby.h | `include/mruby.h` | ヘッダ | mrb_state構造体定義 |
| gc.c | `src/gc.c` | ソース | mrb_gc_init/mrb_gc_destroy |
