言語理論とコンパイラ
第十五回:
実行環境、仮想計算機、ゴミ集め、動的コンパイラ
2014年 7 月 18 日
http://www.sw.it.aoyama.ac.jp/2014/Compiler/lecture15.html
Martin J. Dürst
© 2005-14 Martin
J. Dürst 青山学院大学
今日の予定
- これからの予定
- 実行環境
- ゴミ集め
- 仮想計算機
- 動的コンパイル
これからの予定
- (7月25日: 補講日)
- 8 月 1日 11:10-12:35 (85分): 期末試験
再配置可能プログラム
- コンパイラはソースプログラム一つを再配置可能プログラム一つにコンパイル
(例: gcc )
- 拡張子の例:
.o
(Unix/Linux) や .obj
(Windows)
- 主な中身:
- 機械コード
- 定数
- 未定義のシンボルのリスト
- 外部参照可能なシンボルのリスト
- アドレスの修正が必要な個所のリスト
再配置可能プログラムの検証
- cygwin などで
nm
コマンドを使用
- 出力の種類の意味:
- 小文字は局所的 (ファイル内限定)
- 大文字はグローバル (ファイル間)
- B/b: BSS、初期化されてないデータ
- D/d: Data、初期化されたデータ
- R/r: Read only、読み専用のデータ
- T/t: Text、プログラムの「文書」
- U: Undefined、未定義
- 実行ファイルにも使用可能
実行環境
コンパイラと一緒の用意が必要
- コマンドライン引数の渡し
- 環境変数の渡し
- 例外処理
- 入出力など様々なライブラリ
- メモリ管理
従来の動的メモリの仕組み
- C の動的メモリの仕組:
- 「なま」のメモリを
malloc
で用意
- 使用完了後
free
でシステムに返却
- C++ の動的メモリの仕組:
new
で新しいオブジェクトを作成
- 使用完了後
delete
でシステムに返却
- 問題点:
- 用意する場所と返す場所の相違
- メモリの返却忘れ (memory leak) や早期返却など
- 対応:
ゴミ集めの概要
- 手動の動的メモリ管理は手間が多く、多くのバグの原因
- メモリが必要な時、
new
などで用意
- メモリの回収を自動化
- これをゴミ集め (garbage collection, GC) と言う
ゴミ集めの仕組み
- ポインタを使用しないプログラム言語では変数などの型が明白
- 動的メモリにて参照される部分が計算可能
- 参照されない部分は使用不可能のため、再利用可能
- ゴミ集めの利点:
- プログラマはメモリ管理に気を取られる必要がない
- プログラム作成の効率が向上
- memory leak などが撲滅
- ゴミ集めの問題点:
- ゴミ集めに時間がかかる
(ゴミ集めのために急にプログラムが止まることがある)
- ゴミ集めのデモ: garbage.rb
(実行中にタスクマネージャでメモリ使用量を監視)
- 現在、動的メモリを自動的に管理する言語がほとんど
(C, C++, Objective C 以外)
ゴミ集めの手法
- 参照カウント GC
- 印掃式 GC
- 複写式 GC
- 世代別 GC
- 上記の組み合わせなど
参照カウント GC
(reference count(ing) GC)
- 動的メモリの部分が参照されている数 (reference count)
を記録
- 参照がコピー (代入) される場合、数を ++
- 参照が上書きされる場合など、数を --
- 参照カウントが 0 になるとき、メモリを回収
- 利点: 負担の分散 (途中で処理が停止する恐れ無し)
- 問題点: 参照のサイクルが残る
印掃式 GC
(mark and sweep GC)
- 全ての動的メモリの部分に印を付ける
- 印を最初に off に
- 静的メモリなどから参照を辿って、
参照可能な動的メモリの部分の印を on に
- 印が off のままのメモリの部分を回収
- 問題点: 一般処理の一時停止
複写式 GC
(copying CG)
- 動的メモリ領域を二つ用意
- 領域の片方だけ使用
- 参照を辿って動的メモリをもう一つの領域にコピー
(参照の書換を含む)
- 利点: 動的メモリの整理
- 問題点: メモリが二倍必要
世代別 GC
(generational GC)
- 長生きのデータと短期的なデータがある
- 動的メモリを二つ以上の「世代」に分割
- 若い世代を頻繁にゴミ集め
- 若い世代を何回か生き残ったものが別の世代へ
- 古い世代の少な目にゴミ集め
- 問題点:
古い世代から若い世代への参照に特別な注意が必要
仮想計算機
- 目的: 移植性の向上、 コンパイラの単純化
- 仕組み:
- (実在しない機械の)
機械コードにプログラムをコンパイル
- このコードを解釈・実行するプログラム (emulator)
を用意
- 例: Pascal, JVM: Java Virtual Machine, Ruby 1.9 (YARV), ...
MacIntosh: 680x0 を PowerPC で実装、PowerPC を i386 系で実装
- 問題点: 機械コードより遅い
(一般的に三倍から十倍)
- 類似物: cygwin, wine, VMWare, Virtual
PC, VirtualBox,...
動的コンパイル
- 目的: 仮想計算機などの効率化
- 仕組み (プログラム実行中):
- よく使われるコード (例えば関数、繰り返し)
の割り出し
- このコードをできるだけ機械の命令に置き換える
- 高度な技法:
- よく使われる引数の値などを割り出し、それ専用のコードの枝分かれを用意
- 問題点: 高度な技術が必要
まとめ
- プログラムでは出力より入力が大変
- 入力は言語理論でモデル化可能
- コンパイラでは字句解析と構文解析に言語理論を使用
- 言語理論や字句解析・構文解析の知識はコンパイラ以外にも応用が多数
- プログラム言語の設計と実装がまだまだ面白い