# 機能設計書 87-GCランタイム

## 概要

本ドキュメントは、Juliaのガベージコレクション（GC）ランタイム機能の設計を記述する。世代別GC（stock GC）を標準実装として提供しつつ、MMTk（Memory Management Toolkit）対応のGCインタフェースも備え、並列マーク・並列スイープによる高効率なメモリ管理を実現する。

### 本機能の処理概要

GCランタイムは、Julia プログラムの実行中にヒープメモリの自動管理を行い、不要になったオブジェクトのメモリを回収する機構である。

**業務上の目的・背景**：Julia は高レベルの動的言語であり、プログラマが手動でメモリ管理を行う必要がないよう自動GCを提供する。数値計算・データサイエンスの用途では大量のオブジェクト割当が発生するため、GCの効率がプログラム全体のパフォーマンスに大きく影響する。世代別GCは短命オブジェクトの高速回収に優れ、並列マーク・並列スイープによりGCポーズ時間を短縮する。

**機能の利用シーン**：Julia プログラムの実行中に自動的に動作する。ユーザーは `GC.gc()` で手動GCトリガー、`GC.enable(false)` でGC一時無効化が可能。

**主要な処理内容**：
1. オブジェクト割当（`jl_gc_small_alloc` / `jl_gc_big_alloc`）: プールアロケータと大オブジェクト割当
2. ライトバリア（`jl_gc_queue_root`）: 世代間参照の追跡
3. マークフェーズ: ルートから到達可能な全オブジェクトのマーキング（並列対応）
4. スイープフェーズ: 未マークオブジェクトの回収（並列対応）
5. ファイナライザ実行: GC回収前のファイナライザ呼び出し
6. GCヒューリスティクス: 次回GCタイミングの決定

**関連システム・外部連携**：コード生成（No.84）でGCルートの挿入が行われる。セーフポイント（No.94）と連携してスレッド同期を行う。メモリ管理（No.90）の下位層として動作。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はランタイム内部機能であり、直接的なUI画面は存在しない |

## 機能種別

計算処理（ランタイムメモリ管理処理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| collect_interval | size_t | No | GC発動間隔（バイト）。デフォルトは ~45MiB（64bit）/ ~12MiB（32bit） | 正の整数 |
| max_total_memory | uint64_t | No | ヒープサイズの上限ソフトリミット。デフォルトは2PiB（64bit） | 正の整数 |
| jl_n_markthreads | int | No | 並列マークスレッド数 | 0以上 |
| jl_n_sweepthreads | int | No | 並行スイープスレッド数（0または1） | 0または1 |

### 入力データソース

- ランタイム初期化パラメータ
- jl_gc_set_max_memory() によるユーザー設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| gc_num | jl_gc_num_t | GC統計情報（割当バイト数、回収バイト数、GC時間等） |
| gc_heap_stats | gc_heapstatus_t | ヒープ統計情報 |
| jl_full_sweep_reasons | uint64_t[] | フルGCの理由別カウンタ |

### 出力先

- GC統計情報は `GC.gc_num()` でJuliaコードから取得可能
- @time マクロでGC時間・割当量が表示される

## 処理フロー

### 処理シーケンス

```
1. GCトリガー判定
   └─ 割当バイト数が collect_interval を超えたらGC発動
2. セーフポイント同期
   └─ jl_safepoint_start_gc で全ミューテータスレッドを停止
3. マークフェーズ
   └─ ルートオブジェクトからの到達可能オブジェクトをマーク
   └─ 並列マーク（gc_n_threads_marking スレッド）
4. スイープフェーズ
   └─ gc_sweep_pool: プールページのスイープ（並列対応）
   └─ gc_sweep_other: 大オブジェクト等のスイープ
   └─ gc_sweep_perm_alloc: 永続割当のスイープ
5. ファイナライザ実行
   └─ 到達不能オブジェクトのファイナライザを実行
6. ヒューリスティクス更新
   └─ 次回GC間隔の調整
7. ミューテータ再開
   └─ 全スレッドのGCポーズを解除
```

### フローチャート

```mermaid
flowchart TD
    A[割当閾値超過] --> B[jl_gc_collect 呼び出し]
    B --> C{jl_gc_running?}
    C -->|Yes: 他スレッドがGC中| D[GC完了を待機]
    C -->|No| E[jl_gc_running = 1]
    E --> F[jl_safepoint_start_gc]
    F --> G[jl_gc_wait_for_the_world]
    G --> H[マークフェーズ開始]
    H --> I[ルートスキャン]
    I --> J[並列マーク]
    J --> K[マーク完了]
    K --> L[スイープフェーズ]
    L --> M[並列プールスイープ]
    M --> N[大オブジェクトスイープ]
    N --> O[ファイナライザ実行]
    O --> P[ヒューリスティクス更新]
    P --> Q[ミューテータ再開]
    Q --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-87-01 | 世代別GC | オブジェクトは若い世代と古い世代に分類され、若い世代が優先的にスイープされる | 全GCサイクル |
| BR-87-02 | プールアロケータ | 2032バイト以下のオブジェクトはプールアロケータで割当、それ以上は malloc/big_alloc | オブジェクト割当時 |
| BR-87-03 | ライトバリア | 古い世代のオブジェクトが若い世代のオブジェクトを参照する場合、ライトバリアでルートセットに追加 | setfield! 等 |
| BR-87-04 | ソフトリミット | max_total_memory は超過可能なソフトリミットであり、プロセスを停止するハードリミットではない | ヒューリスティクス判定 |
| BR-87-05 | 保守的マーキング | support_conservative_marking フラグにより、C拡張からの保守的なルートスキャンをサポート | 外部GC拡張使用時 |

### 計算ロジック

プールサイズクラス: GC_MAX_SZCLASS（2032バイト）以下のオブジェクトに対して、サイズクラス別のプールを管理。

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

本機能はデータベースを使用しない。

### 操作別データベース影響一覧

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | メモリ不足 | ヒープが max_total_memory を超過 | GC圧力通知コールバック。最終手段として OOM abort |
| - | ファイナライザ例外 | ファイナライザ内で例外発生 | 例外をキャッチして無視（GCは続行） |

### リトライ仕様

メモリ不足時はフルGCを再試行する。

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

GCはセーフポイントメカニズムにより全ミューテータスレッドを同期停止させた状態で実行される。

## パフォーマンス要件

- GCポーズ時間は可能な限り短くすべき（並列マーク・並列スイープで対応）
- デフォルトの collect_interval は ~45MiB（64bit）で、小さすぎるとGC頻度が高くなりオーバーヘッドが増加
- max_pause 統計で最大ポーズ時間を監視可能

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

- GCはメモリ管理の基盤であり、バグがあるとメモリ破壊・情報漏洩のリスクがある
- ファイナライザはユーザーコードを実行するため、GC中の状態遷移に注意が必要

## 備考

- MMTk対応により、将来的にGCアルゴリズムの切り替えが可能
- gc-interface.h に jl_gc_num_t 構造体が定義されており、Base.timing.jl と同期が必要
- GCページプロファイラ（gc-page-profiler.h）、ヒープスナップショット（gc-heap-snapshot.h）等のデバッグツールが利用可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | gc-interface.h | `src/gc-interface.h` | jl_gc_num_t 構造体（28-80行目）: GC統計情報の全フィールド定義 |
| 1-2 | gc-stock.c | `src/gc-stock.c` | gc_heap_stats（18行目）、各種グローバル変数（32-78行目）: GCの状態変数 |

**読解のコツ**: gc-interface.h のコメントが各フィールドの意味を詳細に説明しているため、まずここを読むとよい。特に「never reset by the runtime」と「reset after every GC cycle」の区別が重要。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | gc-stock.c | `src/gc-stock.c` | jl_gc_collect（内部実装）: GCのメインエントリーポイント |
| 2-2 | gc-stock.c | `src/gc-stock.c` | 同期コメント（81-100行目）: GC同期メカニズムの詳細解説 |

**主要処理フロー**:
1. **81-100行目**: GC同期の設計説明コメント（必読）
2. jl_gc_collect: jl_gc_running の原子的更新、セーフポイント開始、マーク・スイープの実行

#### Step 3: 割当処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | gc-stock.c | `src/gc-stock.c` | jl_gc_small_alloc（780行目）: プールからの小オブジェクト割当 |
| 3-2 | gc-stock.c | `src/gc-stock.c` | jl_gc_big_alloc（468行目）: 大オブジェクトの malloc 割当 |
| 3-3 | gc-stock.c | `src/gc-stock.c` | gc_add_page（705行目）: プールへの新ページ追加 |

#### Step 4: マーク・スイープを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | gc-stock.c | `src/gc-stock.c` | gc_mark_finlist（2178行目）: ファイナライザリストのマーク |
| 4-2 | gc-stock.c | `src/gc-stock.c` | gc_sweep_pool（1363行目）: プールページのスイープ |
| 4-3 | gc-stock.c | `src/gc-stock.c` | gc_sweep_page（863行目）: 個別ページのスイープ |

#### Step 5: MMTk対応を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | gc-mmtk.c | `src/gc-mmtk.c` | MMTk バインディング（1-60行目）: MMTk の初期化とAPI |
| 5-2 | gc-interface.h | `src/gc-interface.h` | GCインタフェース定義: サードパーティGCが実装すべきAPI |

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

```
jl_gc_collect (GCトリガー)
    |
    +-- jl_safepoint_start_gc (全スレッド停止)
    +-- jl_gc_wait_for_the_world
    |
    +-- マークフェーズ
    |      +-- gc_mark_roots (ルートスキャン)
    |      +-- gc_mark_finlist (ファイナライザリスト)
    |      +-- gc_mark_queue_obj (オブジェクトマーク)
    |      +-- gc_mark_queue_objarray (配列マーク)
    |
    +-- スイープフェーズ
    |      +-- gc_sweep_pool (プールスイープ)
    |      |      +-- gc_sweep_page (ページ単位)
    |      +-- gc_sweep_other (大オブジェクト等)
    |      +-- gc_sweep_perm_alloc (永続割当)
    |
    +-- ファイナライザ実行
    +-- ヒューリスティクス更新
```

### データフロー図

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

ルートセット          --> マークフェーズ             --> マークビットマップ
マークビットマップ    --> スイープフェーズ           --> 回収済みメモリ
回収済みメモリ        --> プール返却                 --> 再利用可能プール
GC統計                --> ヒューリスティクス         --> 次回collect_interval
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| gc-stock.c | `src/gc-stock.c` | ソース | 標準GC（世代別GC）の実装 |
| gc-mmtk.c | `src/gc-mmtk.c` | ソース | MMTk対応GCの実装 |
| gc-interface.h | `src/gc-interface.h` | ヘッダ | GCインタフェース定義（jl_gc_num_t等） |
| gc-common.c | `src/gc-common.c` | ソース | GC共通処理（統計、コールバック） |
| gc-common.h | `src/gc-common.h` | ヘッダ | GC共通データ構造 |
| gc-stock.h | `src/gc-stock.h` | ヘッダ | stock GC固有のデータ構造 |
| gc-alloc-profiler.h | `src/gc-alloc-profiler.h` | ヘッダ | GC割当プロファイラ |
| gc-heap-snapshot.h | `src/gc-heap-snapshot.h` | ヘッダ | ヒープスナップショット |
| gc-page-profiler.h | `src/gc-page-profiler.h` | ヘッダ | ページプロファイラ |
| safepoint.c | `src/safepoint.c` | ソース | GCセーフポイント機構 |
