next up previous
Next: 7.2 sweep Up: 7 ガーベッジコレクション Previous: 7 ガーベッジコレクション

7.1 mark

使われているノードをマークするための関数です. ノードのフラグにMARKビットをたてるという処理を行なっています. マークをつけたノードは,sweepの中でそのマークを取り外します.

/* mark - mark all accessible nodes */
LOCAL mark(ptr)
  LVAL ptr;
{
    register LVAL this,prev,tmp;
    int type,i,n;

    /* initialize */
    prev = NIL;
    this = ptr;

    /* mark this list */
    for (;;) {

        /* descend as far as we can */
        while (!(this->n_flags & MARK))

            /* check cons and unnamed stream nodes */
            if ((type = ntype(this)) == CONS ||
                                  type == USTREAM) {
                if (tmp = car(this)) {
                    this->n_flags |= MARK|LEFT;
                    rplaca(this,prev);
                }
                else if (tmp = cdr(this)) {
                    this->n_flags |= MARK;
                    rplacd(this,prev);
                }
                else {            /* both sides nil */
                    this->n_flags |= MARK;
                    break;
                }
                prev = this;      /* step down the branch */
                this = tmp;
            }

            /* mark other node types */
            else {
                this->n_flags |= MARK;
                switch (type) {
                case SYMBOL:
                case OBJECT:
                case VECTOR:
                case CLOSURE:
                case STRUCT:
                    for (i = 0, n = getsize(this);
                                         --n >= 0; ++i)
                        if (tmp = getelement(this,i))
                            mark(tmp);
                    break;
                }
                break;
            }

    /* backup to a point where we can continue descending */
        for (;;)

            /* make sure there is a previous node */
            if (prev) {
                if (prev->n_flags & LEFT) {
                    /* came from left side */
                    prev->n_flags &= ~LEFT;
                    tmp = car(prev);
                    rplaca(prev,this);
                    if (this = cdr(prev)) {
                        rplacd(prev,tmp);                       
                        break;
                    }
                }
                else {      /* came from right side */
                    tmp = cdr(prev);
                    rplacd(prev,this);
                }
                /* step back up the branch */
                       this = prev;
                prev = tmp;
            }

            /* no previous node, must be done */
            else
                return;
    }
}


generated through LaTeX2HTML. M.Inaba 平成18年5月6日