Gauche のオブジェクトの管理について復習

一番基本的なオブジェクトの型として ScmObj という型が定義されています。また、直下で ScmClass 型も定義されています。コメント含め以下に引用。

/*
 * An opaque pointer.  All Scheme objects are represented by
 * this type.
 */
typedef struct ScmHeaderRec *ScmObj;

/*
 * The class structure.  ScmClass is actually a subclass of ScmObj.
 */
typedef struct ScmClassRec ScmClass;

とりあえず ScmHeaderRec 構造体と ScmClassRec 構造体について確認を。

ScmHeaderRec 構造体

gauche.h にて定義されています。

/* A common header for heap-allocated objects */
typedef struct ScmHeaderRec {
    ScmByte *tag;                /* private.  should be accessed
                                    only via macros. */
} ScmHeader;

#define SCM_HEADER       ScmHeader hdr /* for declaration */

コメントも引用させて頂いているので用途も分かります。直下で定義のためのマクロも定義されています。ScmClassRec はメタなオブジェクトだったような気がしてますがとりあえずスルーで。

タグ

LSB な 2 - 4 bit でオブジェクトの切り分けをしてます。例えば以下なマクロで切り分け。

/*
 * PRIMARY TAG IDENTIFICATION
 */

#define	SCM_TAG(obj)     (SCM_WORD(obj) & 0x03)
#define SCM_PTRP(obj)    (SCM_TAG(obj) == 0)

/*
 * IMMEDIATE OBJECTS
 */

#define SCM_IMMEDIATEP(obj) ((SCM_WORD(obj)&0x0f) == 6)

SCM_TAG では LSB な 2 bit を取り出して云々ですね。

  • 0 ならポインタ (基本的にはペア?)
  • 1 なら符号付き整数
  • 2 ならその他諸々なオブジェクト
  • 3 なら 0 の場合以外の heap-allocated object

という形で切り分けてます。上で引用してるコードの末端は 2 の場合で 4 bit を取り出したら 6 の場合を切り分けるためのマクロになっています。オブジェクトの種類を切り分けるために用意されているマクロを引用してみます。
整数かどうか。

#define SCM_INTP(obj)        (SCM_TAG(obj) == 1)

文字かどうか。

#define	SCM_CHARP(obj)          ((SCM_WORD(obj)&0x07L) == 2)

heap-allcated obuject かどうか。

#define SCM_HOBJP(obj)  (SCM_PTRP(obj)&&SCM_TAG(SCM_OBJ(obj)->tag)==3)

あら、これどーゆー意味かな。ちなみに SCM_PAIRP マクロは以下な定義になってます。

#define SCM_PAIRP(obj)  (SCM_PTRP(obj)&&SCM_TAG(SCM_OBJ(obj)->tag)!=0x03)

ええと、SCM_HOBJP 直上に記載されてるコメントが以下になってます。

/*
 * HEAP ALLOCATED OBJECTS
 *
 *  A heap allocated object has its class tag in the first word
 *  (except pairs).  Masking the lower two bits of class tag
 *  gives a pointer to the class object.
 */

ええとペア以外のオブジェクトの最初の word は class object へのポインタになってて、LSB な 2 bit が 1 でマスクされてるのか。

つうか

オブジェクト指向なナニを、ではなくて配列で map が、とか配列なオブジェクトのアクセサが云々、に最適化された仕組みを検討した方が良いのかどうか。

あら?

つうか Ruby も GC 使ってるんでしたっけ。RHG 読むのが某所で流行ってるらしいですが、ぼくも確認してみようかな。
# と思って Gauche のソースを確認し始めたのを今思いだしてたりして (ぇ

shiro さんからフォロー頂きました

曰く、

ワードの下2ビットが00ならポインタで、そのポインタが指してる先のワードの下2ビットが3ならペア以外のヒープアロケーテッドオブジェクト、それ以外ならペアです。ScmObjとしてのワードで下2ビットが11になることは決して無いので、ペアを2ワード(carとcdr)のみにしてタグワード無しでも区別ができます。


とのこと。じつは gauche.h をさらっと撫ぜた程度のリハビリなのでツッコミどころ満載なのだろうなとorz
ぶっちゃけてしまうと高速さを要求される行列演算な実装をしなければ、というナニがありまして、オブジェクティブなフレームワークがあったら面白いのかどうなのか、という発想でこのあたりを掘削させて頂いてた次第です。
そういった意味では当り前ですが cons なペアだったりそれを組合せたリスト、という_もの_に特化した実装になってるのか。ちょい微妙に要求されてる機能とは違うカンジなのかどうか。直接アクセスな要求があるので、なんですよね。