Region-based Memory Management in Cyclone について 発表者 : 前田俊行.

Slides:



Advertisements
Similar presentations
アルゴリズムと データ構造 第 3 回 基本的なデータ構造(2) : 配列 1. 前回の復習 アルゴリズムの計算量 最悪(最大)計算量 計算量の漸近的評価 (オーダ)  多項式時間アルゴリズム( polynomial time algorithm )  指数時間アルゴリズム( exponential.
Advertisements

【事例演習5】  字句解析     解 説  “ハッシュを用いた字句解析の方法”.
アルゴリズムとデータ構造 第2回 線形リスト(復習).
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
5.データ構造入門 5-1.連結リスト(Linked List) 5-2.スタック(Stack) 5-3.キュー(Queue)
ISD実習E 2009年6月29日 LISPシステム入門 (第5回) 関数ポインタ eval システム関数.
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
情報工学概論 (アルゴリズムとデータ構造)
第8回 プログラミングⅡ 第8回
アルゴリズムとデータ構造 2011年6月13日
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
アルゴリズムとデータ構造 第2回 線形リスト(復習その2).
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
2007/1/11 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井 英二郎
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
第3回 配列,構造体,ポインタ ~ データ構造について学ぶための基礎~
TAL : Typed Assembly Language について
プログラミング論 関数ポインタ と 応用(qsort)
プログラミング2 関数
精密工学科プログラミング基礎 第10回資料 (12/18実施)
プログラミング 4 記憶の割り付け.
アルゴリズムとデータ構造 補足資料11-1 「mallocとfree」
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
メモリの準備 メモリには、その準備の方法で2種類ある。 静的変数: コンパイル時にすでにメモリのサイズがわかっているもの。 普通の変数宣言
プログラミング入門2 第11回 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
A Provably Sound TAL for Back-end Optimization について
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
データ構造と アルゴリズム 第五回 知能情報学部 新田直也.
一時的な型 長谷川啓
フロントエンドとバックエンドのインターフェース
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
明星大学 情報学科 2012年度 後期   情報技術Ⅱ   第8回
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
6.データ構造入門 6-1.連結リスト(Linked List) 6-2.スタック(Stack) 6-3.キュー(Queue)
11: 動的メモリ確保 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング 3 2 次元配列.
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
アルゴリズムとデータ構造 2012年6月11日
アルゴリズムとデータ構造1 2009年6月15日
ネットワーク・プログラミング Cプログラミングの基礎.
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
11: 動的メモリ確保 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
SMP/マルチコアに対応した 型付きアセンブリ言語
コンパイラ 第12回 実行時環境 ― 変数と関数 ― 38号館4階N-411 内線5459
アルゴリズムとデータ構造 2010年6月17日
ソフトウェア工学 知能情報学部 新田直也.
11: 動的メモリ確保 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
データ構造と アルゴリズム 第四回 知能情報学部 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
プログラミング演習II 2003年12月10日(第7回) 木村巌.
情報処理Ⅱ 小テスト 2005年2月1日(火).
TList リスト構造とは? 複数のデータを扱うために、 データの内容と、次のデータへのポインタを持つ構造体を使う。
プログラミング演習II 2003年10月29日(第2,3回) 木村巌.
プログラミング 3 ポインタ(1).
プログラミング 2 静的変数.
Presentation transcript:

Region-based Memory Management in Cyclone について 発表者 : 前田俊行

Cyclone とは ? 安全な C の方言 – 型による静的安全性チェック – 配列境界検査などの動的安全性チェック それでいてプログラマに低レベルなメ モリ制御をさせたい

Cyclone プログラムの例 ほとんど C と変わらない – 書換率 = 10% 以下 ( 著者らの経験による ) void factorial(int* result, int n) { int x = 1; if (n > 1) { factorial(&x, n – 1); } *result = x * n; }

Cyclone で region ベースメモリ 管理が必要なわけ スタックにデータを置けるようにした い – そしてそのデータへのポインタを使いたい void factorial(int* result, int n) { int x = 1; if (n > 1) { factorial(&x, n – 1); } *result = x * n; } ポインタ操作 スタック上に データを置く

Region ベースメモリ管理と は ? メモリの確保と解放を Region という単位 で行う手法 Region は LIFO に確保、解放される

LIFO な region の確保と解放 Region の確保 = スタックへ push Region の解放 = スタックから pop

Region の種類 : 2 つ 静的 region – 実行時にサイズが変わらない region – 本当のメモリスタック上に確保できる 動的 region – 実行時にサイズが変わるかもしれない region – メモリスタック上には確保できない

Cyclone における Region の種 類 関数 region ( 静的 region) ローカルブロック region ( 静的 region) 動的 region ヒープ region ( 動的 region)

関数 Region ( 静的 region) 関数の引数を保存する region int sys_mlock(int start, int length) { … } 関数 region int start int length Region スタック 関数呼び出し 新たに region を生成

関数 Region ( 静的 region) 関数の引数を保存する region int sys_mlock(int start, int length) { … } Region スタック 関数からのリターン 生成した region を解放

ローカルブロック Region ( 静的 region) ローカル変数を保存する region { int i; struct stat s; … } Region スタック ローカルブロック region int i struct stat s

動的 Region region プリミティブによって確保される region Region スタック 動的 region int i struct stat s region x { int i; struct stat s; … }

動的 Region の特徴 rnew プリミティブで動的にメモリを確保で きる region x { int? array = rnew(x) { for i < n : i }; … } Region スタック 動的 region Int? array Region ハンドル Region ハンドルを指定して 長さ n の配列をメモリに確保 長さ n の配列

ヒープ region ( 動的 region) プログラム実行中ずっと存在する region グローバル変数を保存する region malloc などがメモリを確保する region int global_counter; … void func() { … malloc(); … } int global_counter ヒープ region 新たに確保

Cyclone における メモリ安全性の保証 メモリ安全性を破るプログラムは コンパイル時の型チェックではじく int* function() { int x; return &x; } メモリ安全でないプログラムの例 型チェックではじ く!

Cyclone におけるポインタ型 全てのポインタ型は、そのポインタが 指している region の情報を保持する ( 例 ) int*ρ –region ρ 中の整数値を指す ρ は region を識別する名前

シンプルな型チェックの例 その 1 int*ρ p; ρ { int x = 0; p = &x; } *p = 123; 型エラー p の宣言の時点では まだ ρ はスコープにない

シンプルな型チェックの例 その 2 int*σ p; ρ { int x = 0; p = &x; } *p = 123; 型エラー p と &x の型が違う p : int*σ &x : int*ρ

関数の Region 多相性 関数はアクセスする region が具体的に分 からなくてもよい char?ρ1 strcpy (char?ρ1, const char?ρ2); char?ρH strdup (const char?ρ); char?ρ1 rstrdup (region_t, const char?ρ2); 例 : Cyclone の文字列ライブラリのプロトタイプ宣言 ( 注 ) ρH はヒープ region を表す

関数の Region 多相性の例 文字列複製関数 strdup の定義 char?ρ1 rstrdup (region_t, const char?ρ2); char?ρH strdup (const char?ρ str) { return rstrdup (heap_regions, str); } ( 注 )ρH, heap_regions は ヒープ region を表す

構造体の Region 多相性 構造体はアクセスする region が具体的に 分からなくてもよい struct List { int*ρ1 head; struct List *ρ2 tail; }; 例 : リスト構造体の定義

Subtyping 型は、より短命な region を持つ型にキャストで きる void f (int b, int*ρ1 p1, int*ρ2 p2) ρ3 { int*ρ3 p; if (b) p = p1; else p = p2; … } ρ1 と ρ2 は ρ3 より長生き なのでキャストできる

うっとおしい region 注釈を無 くす 巧みな “ デフォルトルール ” によって プログラマが明示しなければならない 注釈の量を減らす – ルール 1: ローカル変数は、推論する – ルール 2: 関数の引数や返り値の region は全 て新しい region を割り当てる – ルール 3: それ以外は全部ヒープ region にし てしまう

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 (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; } ルール 2 より引数には 新しい region 名を与える 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; } ルール 3 により ヒープ region となる 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; } ルール 1 により推論 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; } ルール 1 により推論 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; } デフォルトルール適用の例 struct List { int*ρ1 head; struct List *ρ2 tail; }; typedef struct List *ρ2 list_t ;

Existential Existential 型とは、型のある部分を抽象 化することによって複数の型を統一的 に扱うための型である Cyclone はこの existential 型をサポート している

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 可能

Existential の pack の例 struct IntFn ∃ α { int (*func)(α); α env; } int read (int*ρ x) { return *x; } L { int x = 0; struct IntFn pkg = {.func = read,.env = &x }; } Existential の pack 型 int*L を抽象化

Existential の unpack の例 struct IntFn ∃ α { int (*func)(α); α env; } int read (int*ρ x) { return *x; } int apply_IntFn(struct IntFn pkg) { let IntFn {.func = f,.env = x } = pkg; return f ( x ); } Existential の unpack 関数 f の型 : int (*)(α) 引数 x の型 : α

Existential と メモリ安全性上の問題 Existential は型を隠蔽してしまうので dangling ポインタが発生する可能性があ る

Existential による dangling ポインタの発生の例 struct IntFn ∃ α { int (*func)(α); α env; } int read (int*ρ x) { return *x; } L1 { struct IntFn pkg; L2 { int x = 0; pkg = {.func = read,.env = &x }; } … } Dangling ポインタ発生! だが型エラーにはならない …

解決策第 1 段階 関数の effect を考慮する –Effect = 関数がアクセスする ( かもしれない )region の集 合 生きている region の集合を追跡し、 呼び出そうとしている関数の effect と比較す る –Effect 中の region は全て生きていなければならな い

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

関数の 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 (τ)

解決策第 2 段階 Region 制約を考慮する –Region 制約 = どの region がどの region より長生きしなければならな いか Existential の定義に region 制約を指定する –Existential を pack するには指定された region 制約を満 たしていなければならない Existential の unpack 後は指定した region 制約が満 たされているとみなして型チェックを行う

Region 制約を指定した existential の例 struct IntFn ∃ α: regions_of (α) <: ρ { int (*func)(α); α env; } regions_of (α) の全ての region が ρ より長生きであるという制約を表す

Region 制約を満たした existential pack の例 struct IntFn ∃ α : regions_of (α) <: ρ { int (*func)(α); α env; } int read (int*ρ x) { return *x; } L { int x = 0; struct IntFn pkg = {.func = read,.env = &x }; } region 制約 L <: L を満たす

Region 制約を満たさない existential pack の例 struct IntFn ∃ α : regions_of (α) <: ρ { int (*func)(α); α env; } int read (int*ρ x) { return *x; } L1 { struct IntFn pkg; L2 { int x = 0; pkg = {.func = read,.env = &x }; } 型エラー region 制約 L1 <: L2 を満たさない

Existential の unpack の例 L { struct IntFn 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 は呼んでも安全!

まとめ Cyclone は region-based メモリ管理を用 いた安全な C の方言である – 安全性は型チェックにより保証される – スタックにデータを置くことが可能で、さ らにポインタで指すことも可能 Existential によって生じるメモリ安全性 の問題は関数の effect と region 制約に よって解決されている

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