PPT - 情報学群

Download Report

Transcript PPT - 情報学群

コンパイラ
2012年11月15日
酒居敬一@A468([email protected])
http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/COMP/2012/index.html
1
コンパイラと実行環境の連携2
メモリに関係するバグを未然に防ぎたい
使用されていないメモリの自動回収・再利用



ごみ集め(Garbage Collection)

メモリの断片が、使用中かどうかを判定
今回の内容


GCのアルゴリズム

トレース式



2
印掃式GC
複写式GC
参照カウント式
トレース式GCの考え方
「参照する」「参照される」という関係を有向グラフ化する



Javaでは、オブジェクト変数は「参照する」関係の出発点


Javaでは、基本型は値型なのでここでは無関係。
木ではないが出発点なので、図では「ルート」としている
「参照される」対象はインスタンス

インスタンスにもオブジェクト変数を定義できるので、グラフになる
GCのアルゴリズム


印掃式



複写式


3
すべてのルートからグラフをたどり、インスタンスに印をつける
最後まで印のつかなかったインスタンスを回収・再利用する
ヒープを2つにわけ、一方の領域がいっぱいになるまで割り付ける
空きがなくなったとき、他方の領域へルートからたどりつつコピーする
レジスタ群
レジスタ R1
データ構造A
…
レジスタ R32
大域変数群
大域変数 a
大域変数 b
データ構造B
データ構造C
実行時スタック
SP→
空き領域
スタックフ
レーム C
スタックフ
レーム B
スタックフ
レーム A
ルート
4
データ構造D
データ構造E
ヒープ領域
印掃式GC (138ページ a) 順に割り付けて使用中
印
レジスタ群
レジスタ R1
データ構造A
…
レジスタ R32
大域変数群
大域変数 a
大域変数 b
印
データ構造B
印
データ構造C
実行時スタック
SP→
空き領域
スタックフ
レーム C
スタックフ
レーム B
スタックフ
レーム A
ルート
5
印
データ構造D
データ構造E
ごみ、空き領域に還元する
ヒープ領域
印掃式GC (138ページ b) GCが作業中
to 領域
レジスタ群
from 領域
データ構造A
レジスタ R1
…
レジスタ R32
データ構造B
大域変数群
大域変数 a
大域変数 b
データ構造C
実行時スタック
SP→
空き領域
スタックフ
レーム C
スタックフ
レーム B
スタックフ
レーム A
ルート
6
データ構造D
データ構造E
ヒープ領域
複写式GC (140ページ a) 順に割り付け中
レジスタ群
レジスタ R1
from 領域
to 領域
データ構造A
データ構造A
済
…
レジスタ R32
大域変数群
大域変数 a
大域変数 b
済
データ構造B
データ構造B
済
データ構造C
データ構造C
実行時スタック
SP→
空き領域
スタックフ
レーム C
スタックフ
レーム B
スタックフ
レーム A
ルート
7
済
データ構造D
データ構造D
データ構造E
ヒープ領域
複写式GC (140ページ b) 空きがなくなりGC起動
複写式GCにおけるデータ構造の移動
複写の際にインスタンスが移動する


ルートからたどっている最中に参照を更新する


参照は、Javaではオブジェクト変数、Cではポインタ
参照への参照(ポインタへのポインタ)を引数に関数を呼ぶ。
1. void updateReference(reference *field){ /* fieldはポインタへのポインタ */
2.
reference ref = *field;
3.
if(ref != null){
4.
if(!alreadyMoved(ref)){
5.
reference new_address = copyToToArea(ref);
6.
*field = new_address;
7.
markAsMoved(ref, new_address);
8.
}
9.
else {
10.
*field = getForwardPointer(ref);
11.
}
12.
}
13. }
8
参照カウント式GC
データ構造の中にカウンタを設けておく


参照されると+1、参照されなくなったら-1する


そのインスタンスを参照しているオブジェクト変数の数になる
オブジェクト変数への代入時に処理
カウンタの値が0になれば空き領域に加え再利用する
欠点もある




カウンタを操作するオーバーヘッドが大きい
「参照する」「参照される」関係グラフにサイクルがあるとき、
そのサイクル全体がルートから到達不可能でも使用中と
誤認識される

9
メモリリークという致命的欠陥
2
レジスタ群
レジスタ R1
データ構造A
…
レジスタ R32
1
データ構造B
大域変数群
大域変数 a
大域変数 b
2
データ構造C
実行時スタック
SP→
空き領域
スタックフ
レーム C
スタックフ
レーム B
スタックフ
レーム A
ルート
10
1
データ構造D
1
データ構造E
ヒープ領域
参照カウント式GC (141ページ)
GCとコンパイラの連携

そもそもポインタが何時何処に存在するのか?

代入以外にも、ポインタからの参照がなくなるときがある



自動変数として消滅するとき
インスタンスが消滅するとき
ポインタとそれ以外の区別方法

参照の在処をコンパイラが提供する


11
データ構造中の参照
実行時スタックおよびレジスタ
データ構造中の参照の在処
class Data {
int field1;
Data field2;
Data field3;
クラスを表すデータ構造
Data
…
…
クラスDataのインスタンス
クラス名
フィールド数
3
フィールド情報
ヘッダ
クラス
field1
field2
field3
12
フィールドに関する情報
フィールド名
オフセット
型
field1
2
int
field2
3
Data
field3
4
Data
データ構造の走査
1. void scanDataStructure(reference ref){
2.
class *k = reference->ヘッダ.クラス;
3.
int number_of_fields = k->フィールド数;
4.
FieldInfo *fields = k->フィールド情報;
5.
6.
for(int i = 0; i < number_of_fields; i++){
7.
FieldInfo *field = &fields[i];
8.
9.
if(is_reference(field->型)){
10.
updateReference(&(ref[field->オフセット]));
11.
}
12.
}
13. }
13
実行時スタックおよびレジスタ中の参照
戻り番地
3
4
12
21
22
23
24
27
33
34
14
変数数
3
3
4
3
3
3
3
3
2
3
変数情報
名前
型
格納先
オフセット
あるいは
レジスタ名
ee
o
ExecEnv*
void
レジスタ
スタックフレーム
R3
-20
実行時スタックおよびレジスタの走査
1. void scanStackFrames(){
2.
StackFrame *frame = lastFrame();
3.
4.
while(frame > stack_bottom){
5.
PCInfo *info = InfoForPC*frame->return_address);
6.
int number_of_variables = info->変数数;
7.
VariableInfo *variables = info->変数情報;
8.
9.
frame = frame->previous_frame;
10.
for(int i = 0; i < number_of_variables; i++){
11.
VariableInfo *variable = &variables[i];
12.
13.
if(is_reference(variable->型)){
14.
if(is_register(variable->格納先)){
15.
updateReference(&frame[variable->オフセット]);
16.
}
17.
else {
18.
updateReference(addressFor(frame, variable->レジスタ名));
19.
}
20.
}
21.
}
22.
}
23. }
15
Q末試験




日時
2012年11月22日2時限目
場所
A106(いつもの講義室)
時間
10時40分から12時10分までの1時間30分
開始後30分過ぎたら退室可
開始後30分までは入室可(遅刻限度)
持ち込んでいいもの
紙の資料、紙の書籍 (紙媒体であればいい)
16