ステート(続)

さて、次は ldo に進もうかと思ったが、その前に lua_State の構造の理解が必須だと思ったので先にそれを解説する。

先週は lua_State の初期化を見た。今週はまず、 lua_State の内部データを眺める。

struct lua_State {
  CommonHeader;
  StkId top;  /* first free slot in the stack */
  StkId base;  /* base of current function */
  global_State *l_G;
  CallInfo *ci;  /* call info for current function */
  StkId stack_last;  /* last free slot in the stack */
  StkId stack;  /* stack base */
  int stacksize;
  CallInfo *end_ci;  /* points after end of ci array*/
  CallInfo *base_ci;  /* array of CallInfo's */
  unsigned short size_ci;  /* size of array `base_ci' */
  unsigned short nCcalls;  /* number of nested C calls */
  lu_byte hookmask;
  lu_byte allowhook;
  lu_byte hookinit;
  int basehookcount;
  int hookcount;
  lua_Hook hook;
  TObject _gt;  /* table of globals */
  GCObject *openupval;  /* list of open upvalues in this stack */
  GCObject *gclist;
  struct lua_longjmp *errorJmp;  /* current error recover point */
  ptrdiff_t errfunc;  /* current error handling function (stack index) */
};

いろいろある。 StkId というのはこれまで明示的に説明を避けてきたが、ようするに TObject* の別名である。ここではこの StkId と、 CallInfo に着目しよう。

lua はもともとスタックマシンだった。今でもスタックをもとに計算をしている(実際にはVMコードはレジスタマシン)。このスタックを意味するのが stack、stack_last、top、base、stacksizeである。

stack はスタックの始点、stack_lastはスタックの終点、 stacksize はスタックの大きさとなる。で、実際のスタックの利用を示しているのが base と top だ。コメントにもあるように、 base は「現在の関数呼出し」のときのベースになるスタック地点を保存する。それに対して top はスタックが積まれるごとに線型に増えていく値である。関数から戻るときには、 base から top までをクリアすればスタックが空になる、とかいった風情になるのだろう。

CallInfo も似たような構造を持つ。 CallInfo はそもそも関数呼出し情報を保持するデータ構造で、新しく関数が呼び出されると CallInfo にデータが積まれる。 end_ci が終点のポインタ、 size_ci がコールスタックの大きさ、 nCcalls は C 関数呼出しの回数である。