mrubyを読む
はじめに †
初期化の際に呼び出されるのはmrb_open()関数のようです。
mrb_open(state.c) †
それでは早速mrb_open()を見てみましょう。
1
2
3
4
5
6
7
|
-
|
|
|
!
| mrb_state*
mrb_open()
{
mrb_state *mrb = mrb_open_allocf(allocf);
return mrb;
}
|
というわけでmrb_open_allocf()に委譲です。
allocf(state.c) †
mrb_open_allocf()に進む前にallocfとは何者なのか見てみましょう。allocfはmrb_open()のすぐ上に書かれています。
1
2
3
4
5
6
7
8
9
10
11
|
-
-
|
|
!
-
|
!
!
| static void*
allocf(mrb_state *mrb, void *p, size_t size)
{
if (size == 0) {
free(p);
return NULL;
}
else {
return realloc(p, size);
}
}
|
というわけでallocfとはメモリ確保・解放関数のようです。mrubyは組み込み向け*1なので独自のメモリアロケーターを使いやすいようになっているのでしょう。
allocfに書いてあることをそのまま書くとallocf、というかmrb_open_allocf()に渡すmrb_allocfの仕様は以下のようになっているようです。
- 第2引数で指定されているメモリ領域を第3引数で指定した量に拡張する(第2引数がNULLの場合は単純に第3引数分メモリ確保する)
- 第3引数が0の場合は第2引数が指すメモリ領域を開放する
2つ目の仕様がなんか気にくわないですがallocfの呼び出しをwrapした馴染みの関数が定義されているのでメモリ解放時に0指定で呼び出すという気持ち悪いことはしないでもOKです。
gc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
-
|
!
-
|
!
-
|
|
|
|
!
-
|
!
| void*
mrb_realloc(mrb_state *mrb, void *p, size_t len)
{
return (mrb->allocf)(mrb, p, len);
}
void*
mrb_malloc(mrb_state *mrb, size_t len)
{
return (mrb->allocf)(mrb, 0, len);
}
void*
mrb_calloc(mrb_state *mrb, size_t nelem, size_t len)
{
void *p = (mrb->allocf)(mrb, 0, nelem*len);
memset(p, 0, nelem*len);
return p;
}
void*
mrb_free(mrb_state *mrb, void *p)
{
return (mrb->allocf)(mrb, p, 0);
}
|
ちなみに、freeが別関数になっていないのは気持ち悪いとか0サイズ指定だとfreeなのは気にくわないとか書いてますが、少しでもmrb_state構造体のサイズを減らす努力かもと思います。う〜ん、でもそんなにメモリが厳しい環境って、allocf中のif文の方が時間的・空間的につらくなるような気も。
mrb_open_allocf(state.c) †
さて、話が長くなりましたがmrb_open_allocf()です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-
|
|
|
|
|
|
|
|
|
|
!
| mrb_state*
mrb_open_allocf(mrb_allocf f)
{
mrb_state *mrb = (f)(NULL, NULL, sizeof(mrb_state));
memset(mrb, 0, sizeof(mrb_state));
mrb->allocf = f;
mrb->current_white_part = MRB_GC_WHITE_A;
mrb_init_heap(mrb);
mrb_init_core(mrb);
mrb_init_ext(mrb);
return mrb;
}
|
見ての通り、mrb_state構造体を確保した後、ヒープやコアライブラリと思えるものを初期化しています。なお、current_white_partというのはGC関連の変数です。
mrb_init_heap()は普通にヒープを初期化しているだけなので飛ばしてmrb_init_core()に進みます。
mrb_init_core(init.c) †
(今ここ!)