唐突ですが、perl5 のスタックについて解説します。Perl5 は stack machine なので、何本かのスタックがあります。これらは構造体 my_perl の中にはいっていて、ithread ありの場合には引数でひきまわされ、なしの場合には global 変数になります。
argument stack
- stack_sp
- stack_base
- stack_max
- 中身
- SV*
引数/返り値のひきわたしなどにつかうメインスタックです。
savestack
- savestack
- savestack_ix
- savestack_max
- 中身
- ANY *
スコープにはいったときに保存して、でるときにリストアするようなデータを一時保存するためのスタックである。
scope の中では、SAVEINT, SAVEI8 などのマクロをつかって、ポインタと元の値を savestack につむことができる。ここでセーブされた値は、スコープをぬけるときに元にもどる。
scope にはいる際に scopestack に現在のインデックスが push され、でるときに pop される。この際、スコープの中でセーブスタックがのびていれば、そのセーブされた値はリストアされる。
スコープスタック
- scopestack
- scopestack_ix
- scopestack_max
- 中身
- savestack_ix
scope に enter したときにつまれる。enter すると、push_scope(); がよばれ、scopestack に現在の savestack_ix の値が push される。
leave したときに pop される。この時の savestack_ix の値が、pop したものよりも大きいと、scope.c の Perl_leave_scope が呼ばれる。
scope にはいる際に scopestack に現在のインデックスが push され、でるときに pop される。この際、スコープの中でセーブスタックがのびていれば、そのセーブされた値はリストアされる。
一時変数スタック
- tmps_stack
- tmps_ix
- tmps_floor
- tmps_max
一時変数を保存するためのスタックである。XS について詳しい人ならば、mortal 変数というとわかりやすいに違いない。mortal な変数がつまれる領域がここである。
ここに詰まれた変数は、スコープからぬけるときに開放される。XS のマクロでいうと FREETMPS; にあたる。FREETMPS は scope.c の Perl_free_tmps を呼ぶことになる。
markstack
- markstack
- markstack_ptr
- markstack_max
- 中身
- stack pointer
スタックマーカ変数である。関数コールの際につかわれる。
markstack には現在のスタックポインタ(sp)の位置を push しておく。その後、XPUSHs() などで引数スタックにどんどん値を push していく。そして関数をすかさずコールする。コールされた関数の中で markstack を pop する。これにより、どこまでが引数かがわかるというわけ。
これにかかわるマクロは以下の2つだ。これらは pp.h に定義されている(push-pop.h の略だとおもう)
#define PUSHMARK(p) \
STMT_START { \
if (++PL_markstack_ptr == PL_markstack_max) \
markstack_grow(); \
*PL_markstack_ptr = (I32)((p) - PL_stack_base);\
} STMT_END
#define POPMARK (*PL_markstack_ptr--)XSUB を書く場合につかう dAXMARK; がまさに POPMARK; している(実際には直接 dAXMARK を呼ぶことはなくて、dXSARGS を呼ぶのだが、dXSARGS が中で dAXMARK をよんでいる)。
#define dAXMARK \
I32 ax = POPMARK; \
register SV **mark = PL_stack_base + ax++
curstack
- curstack
- curstackinfo
- mainstack(curstack の base)
stackinfo 構造体がつまれれている。現在のコンテキスト情報がはいっている。詳細は後で。