Region-based Memory Management in Cyclone について

40
Region-based Memory Managem ent in Cyclone にににに ににに : にににに

description

Region-based Memory Management in Cyclone について. 発表者 : 前田俊行. Cyclone とは ?. 安全な C の方言 型による静的安全性チェック 配列境界検査などの動的安全性チェック それでいてプログラマに低レベルなメモリ制御をさせたい. Cyclone プログラムの例. ほとんど C と変わらない 書換率 = 10% 以下 ( 著者らの経験による ). void factorial(int* result, int n) { int x = 1; if (n > 1) { - PowerPoint PPT Presentation

Transcript of Region-based Memory Management in Cyclone について

Page 1: Region-based Memory Management in Cyclone について

Region-based Memory Managementin Cycloneについて

発表者 : 前田俊行

Page 2: Region-based Memory Management in Cyclone について

Cyclone とは ?

• 安全な C の方言– 型による静的安全性チェック– 配列境界検査などの動的安全性チェック

• それでいてプログラマに低レベルなメモリ制御をさせたい

Page 3: Region-based Memory Management in Cyclone について

Cyclone プログラムの例

• ほとんど C と変わらない– 書換率 = 10% 以下 ( 著者らの経験による )

void factorial(int* result, int n){

int x = 1;

if (n > 1) {factorial(&x, n – 1);

}*result = x * n;

}

Page 4: Region-based Memory Management in Cyclone について

Cyclone で region ベースメモリ管理が必要なわけ

• スタックにデータを置けるようにしたい– そしてそのデータへのポインタを使いた

いvoid factorial(int* result, int n){

int x = 1;

if (n > 1) {factorial(&x, n – 1);

}*result = x * n;

}

ポインタ操作

ポインタ操作

スタック上にデータを置く

Page 5: Region-based Memory Management in Cyclone について

Region ベースメモリ管理とは ?

• メモリの確保と解放を Region という単位で行う手法

• Region は LIFO に確保、解放される

Page 6: Region-based Memory Management in Cyclone について

LIFO な region の確保と解放

Region の確保 =スタックへ push

Region の解放 =スタックから pop

Page 7: Region-based Memory Management in Cyclone について

Region の種類 : 2 つ

• 静的 region– 実行時にサイズが変わらない region– 本当のメモリスタック上に確保できる

• 動的 region– 実行時にサイズが変わるかもしれない regi

on– メモリスタック上には確保できない

Page 8: Region-based Memory Management in Cyclone について

Cyclone における Region の種類

• 関数 region ( 静的 region)

• ローカルブロック region ( 静的 region)

• 動的 region

• ヒープ region ( 動的 region)

Page 9: Region-based Memory Management in Cyclone について

関数 Region ( 静的 region)

• 関数の引数を保存する region

int sys_mlock(int start, int length){

…}

関数 region

int start

int length

Region スタック

関数呼び出し

新たに region を生成

Page 10: Region-based Memory Management in Cyclone について

関数 Region ( 静的 region)

• 関数の引数を保存する region

int sys_mlock(int start, int length){

…}

Region スタック関数からのリターン

生成した region を解放

Page 11: Region-based Memory Management in Cyclone について

ローカルブロック Region( 静的 region)

• ローカル変数を保存する region

{int i;struct stat s;

…}

Region スタック

ローカルブロックregion

int i

struct stat s

Page 12: Region-based Memory Management in Cyclone について

動的 Region

• region プリミティブによって確保される region

Region スタック

動的 region

int i

struct stat s

region x {int i;struct stat s;

…}

Page 13: Region-based Memory Management in Cyclone について

動的 Region の特徴

• rnew プリミティブで動的にメモリを確保できる

region x {int? array =

rnew(x) { for i < n : i };…

}

Region スタック

動的 region

Int? array

Region ハンドル

Region ハンドルを指定して長さ n の配列をメモリに

確保

長さ n の配列

Page 14: Region-based Memory Management in Cyclone について

ヒープ region ( 動的 region)

• プログラム実行中ずっと存在する region• グローバル変数を保存する region• malloc などがメモリを確保する region

int global_counter;…void func(){

…malloc();…

}

int global_counter

ヒープ region

新たに確保

Page 15: Region-based Memory Management in Cyclone について

Cyclone におけるメモリ安全性の保証

• メモリ安全性を破るプログラムはコンパイル時の型チェックではじく

int* function(){

int x;

return &x;}

メモリ安全でないプログラムの例

型チェックではじく!

Page 16: Region-based Memory Management in Cyclone について

Cyclone におけるポインタ型

• 全てのポインタ型は、そのポインタが指している region の情報を保持する

• ( 例 ) int*ρ– region ρ 中の整数値を指す

• ρ は region を識別する名前

Page 17: Region-based Memory Management in Cyclone について

シンプルな型チェックの例その 1

int*ρ p;ρ {

int x = 0;

p = &x;}*p = 123;

型エラーp の宣言の時点では

まだ ρ はスコープにない

Page 18: Region-based Memory Management in Cyclone について

シンプルな型チェックの例その 2

int*σ p;ρ {

int x = 0;

p = &x;}*p = 123;

型エラーp と &x の型が違

うp : int*σ

&x : int*ρ

Page 19: Region-based Memory Management in Cyclone について

関数の Region 多相性

• 関数はアクセスする region が具体的に分からなくてもよい

char?ρ1 strcpy <ρ1, ρ2> (char?ρ1, const char?ρ2);char?ρH strdup <ρ> (const char?ρ);char?ρ1 rstrdup <ρ1, ρ2> (region_t<ρ1>, const char?ρ2);

例 : Cyclone の文字列ライブラリのプロトタイプ宣言

( 注 )   ρH はヒープ region を表す

Page 20: Region-based Memory Management in Cyclone について

関数の Region 多相性の例

• 文字列複製関数 strdup の定義

char?ρ1 rstrdup <ρ1, ρ2> (region_t<ρ1>, const char?ρ2);

char?ρH strdup <ρ> (const char?ρ str){

return rstrdup <ρH, ρ> (heap_regions, str);}

( 注 )ρH, heap_regions は ヒープ region を表す

Page 21: Region-based Memory Management in Cyclone について

構造体の Region 多相性

• 構造体はアクセスする region が具体的に分からなくてもよい

struct List <ρ1, ρ2> {int*ρ1 head;struct List <ρ1, ρ2>*ρ2 tail;

};

例 : リスト構造体の定義

Page 22: Region-based Memory Management in Cyclone について

Subtyping

• 型は、より短命な region を持つ型にキャストできる

void f<ρ1, ρ2> (int b, int*ρ1 p1, int*ρ2 p2)ρ3 {

int*ρ3 p;if (b)

p = p1;else

p = p2;…

}

ρ1 と ρ2 は ρ3 より長生きなのでキャストできる

Page 23: Region-based Memory Management in Cyclone について

うっとおしい region 注釈を無くす

• 巧みな“デフォルトルール”によってプログラマが明示しなければならない注釈の量を減らす– ルール 1: ローカル変数は、推論する– ルール 2: 関数の引数や返り値の region は

全て新しい region を割り当てる– ルール 3: それ以外は全部ヒープ region に

してしまう

Page 24: Region-based Memory Management in Cyclone について

list_t list_copy(list_t lst){

list_t res = NULL;

for (list_t t = lst; t != NULL; t = t->tail)res = new List(new *t->hd, res);

return res;}

list_t list_copy <ρ1, ρ2> (list_t <ρ1, ρ2> lst){

list_t res = NULL;

for (list_t t = lst; t != NULL; t = t->tail)res = new List(new *t->hd, res);

return res;}

ルール 2 より引数には新しい region 名を与え

list_t <ρH, ρH> list_copy <ρ1, ρ2> (list_t <ρ1, ρ2> lst){

list_t res = NULL;

for (list_t t = lst; t != NULL; t = t->tail)res = new List(new *t->hd, res);

return res;}

ルール 3 によりヒープ region となる

list_t <ρH, ρH> list_copy <ρ1, ρ2> (list_t <ρ1, ρ2> lst){

list_t <ρH, ρH> res = NULL;

for (list_t t = lst; t != NULL; t = t->tail)res = new List(new *t->hd, res);

return res;}

ルール 1 により推論

list_t <ρH, ρH> list_copy <ρ1, ρ2> (list_t <ρ1, ρ2> lst){

list_t <ρH, ρH> res = NULL;

for (list_t <ρ1, ρ2> t = lst; t != NULL; t = t->tail)res = new List(new *t->hd, res);

return res;}

ルール 1 により推論

list_t <ρH, ρH> list_copy <ρ1, ρ2> (list_t <ρ1, ρ2> lst){

list_t <ρH, ρH> res = NULL;

for (list_t <ρ1, ρ2> t = lst; t != NULL; t = t->tail)res = new List(new *t->hd, res);

return res;}

デフォルトルール適用の例struct List <ρ1, ρ2> {

int*ρ1 head;struct List <ρ1, ρ2>*ρ2 tail;

};typedef struct List <ρ1, ρ2>*ρ2 list_t <ρ1, ρ2>;

Page 25: Region-based Memory Management in Cyclone について

Existential

• Existential 型とは、型のある部分を抽象化することによって複数の型を統一的に扱うための型である

• Cyclone はこの existential 型をサポートしている

Page 26: Region-based Memory Management in Cyclone について

Existential 型の例

struct IntFn ∃α {int (*func)(α);α env;

}

Existential 型

struct IntFn_int {int (*func)(int*ρ);int*ρ env;

}

struct IntFn_List {int (*func)(struct List*ρ);struct List* env;

}

型変数 α を実際の型で置き換えた型の値

は全てこの existential型に変換 (pack とい

う ) できるPack 可能 Pack 可能

Page 27: Region-based Memory Management in Cyclone について

Existential の pack の例struct IntFn α {∃

int (*func)(α);α env;

}int read <ρ> (int*ρ x) { return *x; }

L {int x = 0;struct IntFn pkg =

<int*L>{ .func = read <L>, .env = &x };}

Existential の pack型 int*L を抽象化

Page 28: Region-based Memory Management in Cyclone について

Existential の unpack の例struct IntFn α {∃

int (*func)(α);α env;

}int read <ρ> (int*ρ x) { return *x; }

int apply_IntFn(struct IntFn<L1> pkg){

let IntFn<α> { .func = f, .env = x } = pkg;return f ( x );

}Existential の unpack関数 f の型 : int (*)

(α)引数 x の型 : α

Page 29: Region-based Memory Management in Cyclone について

Existential とメモリ安全性上の問題

• Existential は型を隠蔽してしまうので dangling ポインタが発生する可能性がある

Page 30: Region-based Memory Management in Cyclone について

Existential によるdangling ポインタの発生の例struct IntFn α {∃

int (*func)(α);α env;

}int read <ρ> (int*ρ x) { return *x; }

L1 {struct IntFn pkg;L2 {

int x = 0;pkg =<int*L2>{ .func = read <L2>, .env = &x };

}…

}

Dangling ポインタ発生!だが型エラーにはならな

い…

Page 31: Region-based Memory Management in Cyclone について

解決策第 1 段階

• 関数の effect を考慮する– Effect =

関数がアクセスする ( かもしれない )region の集合

• 生きている region の集合を追跡し、呼び出そうとしている関数の effect と比較する– Effect 中の region は全て生きていなければならな

Page 32: Region-based Memory Management in Cyclone について

関数の effect はどう求めるか ?

• 引数と返り値の型にあらわれる regionを全て effect に含める– 最も conservative な推論– 利点 : プロトタイプ宣言だけで effect を

求められる

Page 33: Region-based Memory Management in Cyclone について

関数の effect の例

普通の関数int*ρ1 f ( int*ρ2, int*ρ1*ρ3); Effect : {ρ1, ρ2, ρ3}

多相型関数int compare(α, α); Effect : { regions_of (α) }

ただし regions_of は以下のとおり : regions_of (int) = 0 ( 空集合 ) regions_of (τ*ρ) = { ρ } regions_of (τ)∪ regions_of ((τ1, … , τn) → τ) = regions_of (τ1) regions_of (τ2) regions_of (τ)∪ ∪

Page 34: Region-based Memory Management in Cyclone について

解決策第 2 段階

• Region 制約を考慮する– Region 制約 =

どの region がどの region より長生きしなければならないか

• Existential の定義に region 制約を指定する– Existential を pack するには指定された region 制約を

満たしていなければならない

• Existential の unpack 後は指定した region 制約が満たされているとみなして型チェックを行う

Page 35: Region-based Memory Management in Cyclone について

Region 制約を指定した existential の例

struct IntFn<ρ> α: regions_of (α) <: ρ {∃int (*func)(α);α env;

}

regions_of (α) の全ての region がρ より長生きであるという制約を表す

Page 36: Region-based Memory Management in Cyclone について

Region 制約を満たした existential pack の例

struct IntFn<ρ> α : regions_of (α) <: ρ {∃int (*func)(α);α env;

}int read <ρ> (int*ρ x) { return *x; }

L {int x = 0;struct IntFn<L> pkg =

<int*L>{ .func = read <L>, .env = &x };}

region 制約 L <: Lを満たす

Page 37: Region-based Memory Management in Cyclone について

Region 制約を満たさない existential pack の例

struct IntFn<ρ> α : regions_of (α) <: ρ {∃int (*func)(α);α env;

}int read <ρ> (int*ρ x) { return *x; }

L1 {struct IntFn<L1> pkg;L2 {

int x = 0;pkg =<int*L2>{ .func = read <L2>, .env = &x };

}}

型エラー region 制約 L1 <: L2 を満たさない

Page 38: Region-based Memory Management in Cyclone について

Existential の unpack の例

L {struct IntFn<L> pkg;…let IntFn<α> { .func = f, .env = x } = pkg;

f ( x );}

struct IntFn<ρ> α : regions_of (α) <: ρ {∃int (*func)(α);α env;

} 関数 f の effect = { regions_of (α) }生きている region = { L }Region 制約 = { regions_of (α) <: L }つまり、関数 f は呼んでも安全!

Page 39: Region-based Memory Management in Cyclone について

まとめ

• Cyclone は region-based メモリ管理を用いた安全な C の方言である– 安全性は型チェックにより保証される– スタックにデータを置くことが可能で、さ

らにポインタで指すことも可能• Existential によって生じるメモリ安全性

の問題は関数の effect と region 制約によって解決されている

Page 40: Region-based Memory Management in Cyclone について

References

• Cyclone homepage http://www.cs.cornell.edu/projects/cyclone

• Region-based Memory Management in Cyclone, Dan Grossman, Greg Morrisett, Trevor Jim, Michael Hicks, Yanling Wang, and James Cheney. PLDI2002. To appear.