BoehmGC解読室 - 1 (small object の allocate)中編

GC_malloc

// malloc.c

void * GC_malloc(size_t lb)
{
    void *op;
    void **opp;
    size_t lg;
    DCL_LOCK_STATE;

    if(SMALL_OBJ(lb)) { /** (1) **/
	lg = GC_size_map[lb]; /** (2) **/
	opp = (void **)&(GC_objfreelist[lg]); /** (3) **/
	LOCK();
        if( EXPECT((op = *opp) == 0, 0) ) {
            UNLOCK();
            return(GENERAL_MALLOC((word)lb, NORMAL)); /** (4) **/
        }
        *opp = obj_link(op);
        obj_link(op) = 0; /** (6) **/
        GC_bytes_allocd += GRANULES_TO_BYTES(lg); /** (5) **/
        UNLOCK();
        return op;
   } else {
       return(GENERAL_MALLOC(lb, NORMAL));
   }
}

(3)GC_objfreelist[lg]

lgには(2)で取得したfreelistのindexが入ります。
さて、このGC_objfreelistには何が入ってるんでしょうか!
という疑問は(4)で説明するとして、ここにはhblk(heap block)へのポインタが入っています。
それで、取得した*oppが0(つまり、まだhblkが割り当てられていない。もしくは使用済)場合に(4)で新たに取得することになります。
もし、hblkが存在した場合には、(6)でhblkへのポインタを、0で初期化しています。
obj_linkはこんなマクロです。

/* Object free list link */
# define obj_link(p) (*(void  **)(p))

0で初期化することで次は新規で割り当ててねって事ですね。
この(6)の前で変数にtempしてるのはこの間にGCされないようにする為だと思われます。
 

EXPECTについて
#if __GNUC__ >= 3
# define EXPECT(expr, outcome) __builtin_expect(expr,outcome)
  /* Equivalent to (expr), but predict that usually (expr)==outcome. */
# define INLINE inline
#else
# define EXPECT(expr, outcome) (expr)
# define INLINE
#endif /* __GNUC__ */

これはgccの最適化を狙ったマクロのようです。
詳しくは
http://www.issei.org/diary/_20030224/d200101a.html#05-1
正直日記
 
使われている意味では

EXPECT((op = *opp) == 0, 0)

falseの方が多いだろうと見越した最適化をするようです。
 

結論

freelistは hblk のポインタの配列になっている。
この行では、指定したindexのポインタを取り出している。
のちに、hblkのポインタを取り出すのに使われる。
(書いててわけわからんくなった。。。図がわかりやすいかな)
 

続きは

webで