Beispiel #1
0
Datei: gc.c Projekt: roby85/Viper
void gc_keep_cells(PTuple *closure) {
    PObject **objs = PSEQUENCE_OBJECTS(closure);
    uint32_t nobjs = PSEQUENCE_ELEMENTS(closure);
    GC_MARK(closure);//mark: closure must not be gc'ed as a normal tuple, no "objects" inside
    while (nobjs--) {
        PObject *obj = objs[nobjs];
        if (obj) {
            debug("keeping cell %x => %x\n", obj, PCELL_ARG(obj));
            obj = PCELL_ARG(obj);
            GC_KEEP(obj);//PCELL_ARG(obj) is a freevar tuple, keep it

        }
    }
}
Beispiel #2
0
bool bch_bucket_add_unused(struct cache *ca, struct bucket *b)
{
	BUG_ON(GC_MARK(b) || GC_SECTORS_USED(b));

	if (CACHE_REPLACEMENT(&ca->sb) == CACHE_REPLACEMENT_FIFO) {
		unsigned i;

		for (i = 0; i < RESERVE_NONE; i++)
			if (!fifo_full(&ca->free[i]))
				goto add;

		return false;
	}
add:
	b->prio = 0;

	if (can_inc_bucket_gen(b) &&
	    fifo_push(&ca->unused, b - ca->buckets)) {
		atomic_inc(&b->pin);
		return true;
	}

	return false;
}
Beispiel #3
0
static bool can_invalidate_bucket(struct cache *ca, struct bucket *b)
{
	return GC_MARK(b) == GC_MARK_RECLAIMABLE &&
		!atomic_read(&b->pin) &&
		can_inc_bucket_gen(b);
}
Beispiel #4
0
/**
 * Marks a LuciLibFuncObj as reachable
 *
 * @param in LuciLibFuncObj
 */
void LuciLibFunc_mark(LuciObject *in)
{
    GC_MARK(in);
}
Beispiel #5
0
/**
 * Marks a LuciFileObj as reachable
 *
 * @param in LuciFileObj
 */
void LuciFile_mark(LuciObject *in)
{
    GC_MARK(in);
}
Beispiel #6
0
Datei: gc.c Projekt: roby85/Viper
//TODO: remove the stack and make a list of used/marked via header!! phead vs ptail
void gc_mark() {
    int i;
    PObject *obj;

    debug( "\n\n>>>>>>>MARK started %x\n", _phead);

    gc_trace();
    gc_keep_root();

    while (_phead) {
        obj = _phead;
        _phead = GCH_NEXT(obj);

        int tt = PTYPE(obj);
        switch (tt) {
            case PBYTEARRAY:
            case PSHORTARRAY:
                if (_PMS(obj)->seq)
                    GC_MARK( _PMS(obj)->seq);
                break;
            case PLIST:
            case PTUPLE: {
                i = PSEQUENCE_ELEMENTS(obj);
                PObject **objs = PSEQUENCE_OBJECTS(obj);
                if (objs) {
                    GC_KEEP_MANY(objs, i);
                    if (PSEQUENCE_BUFFER(obj)) {
                        GC_MARK(PSEQUENCE_BUFFER(obj));
                    }
                }
            }
            break;

            case PFSET:
            case PSET:
            case PDICT: {
                PDict *tmp = (PDict *)obj;
                int e = 0;
                HashEntry *ee;
                while ( (ee = phash_getentry(tmp, e++)) != NULL ) {
                    GC_KEEP_NOTNULL(ee->key);
                    if (tt == PDICT)
                        GC_KEEP_NOTNULL(ee->value);
                }
                if (tmp->entry)
                    GC_MARK(tmp->entry);
            }
            break;

            case PFUNCTION: {
                PFunction *tmp = (PFunction *)obj;
                if (tmp->defargs) GC_KEEP_MANY(tmp->storage, tmp->defargs);
                //TODO: the following can be optimized by avoiding the check on names...
                //and use macros to access function fields for portability...
                if (tmp->defkwargs) GC_KEEP_MANY(tmp->storage + tmp->defargs, 2 * tmp->defkwargs);
                if (PCODE_CELLVARS(PCODE_MAKE(tmp->codeobj))) {
                    obj = (PObject *)PFUNCTION_GET_CLOSURE(tmp);
                    GC_KEEP(obj);
                    //if (obj)
                    //   gc_keep_cells((PTuple *)obj);
                }
            }
            break;

            case PMETHOD: {
                PMethod *tmp = (PMethod *)obj;
                GC_KEEP(tmp->self);
                GC_KEEP(tmp->fn);
            }
            break;

            case PCLASS: {
                PClass *tmp = (PClass *)obj;
                GC_KEEP(tmp->bases);
                GC_KEEP(tmp->dict);
            }
            break;

            case PINSTANCE: {
                PInstance *tmp = (PInstance *)obj;
                GC_KEEP(tmp->base);
                GC_KEEP(tmp->dict);
            }
            break;

            case PITERATOR:
                GC_KEEP(   ((PIterator *)obj)->iterable );
                break;

            case PFRAME: {
                //debug("checking frame %i\n", obj);
                PFrame *tmp = (PFrame *)obj;
                PCode *code = PCODE_MAKE(tmp->code);
                GC_KEEP(tmp->parent);
                //GC_KEEP(tmp->block);
                GC_KEEP_MANY(PFRAME_PSTACK(tmp), tmp->sp);
                GC_KEEP_MANY(PFRAME_PLOCALS(tmp, code), code->nlocals);
                if (PCODE_HASVARS(code))
                    GC_KEEP_MANY(PFRAME_VARS(tmp, code), 2);

                /*if (PCODE_FREEVARS(code)) {
                    obj = PFRAME_TFREEVARS(tmp,code);//(PObject *)PFRAME_FREEVARS(tmp);
                    debug("keeping freevars %x for %x\n", obj, tmp);
                    GC_KEEP(obj);
                }
                debug("FRAME %x %i %i\n", tmp, PCODE_CELLVARS(code), PCODE_FREEVARS(code));
                if (PCODE_CELLVARS(code)) {
                    obj = (PObject *)PFRAME_CELLVARS(tmp);
                    debug("keeping cells for %x\n", obj);
                    GC_KEEP(obj);
                    //if (obj)
                    //    gc_keep_cells((PTuple *)obj);
                }
                */
            }
            break;
            /*case PBLOCK:
                //debug("checking block %i\n", obj);
                GC_KEEP(((PBlock *)obj)->next);
                break;
            */
            case PSYSOBJ: {
                PSysObject *tmp = (PSysObject *) obj;
                SYSLOCK();
                if (tmp->type == PSYS_TIMER) {
                    GC_KEEP(tmp->sys.timer.fn.fn);
                    GC_KEEP(tmp->sys.timer.fn.args);
                }
                SYSUNLOCK();
            }
            break;

            default:
                break;
        }
        //no need to mark obj. It has already been marked in gc_keep
        //GC_MARK(obj);
    }

    gc_trace();
    _phead = NULL;
    obj = PNT(_vm.thlist);
    do {
        PThread *pth = (PThread *)obj;
        debug( "Scanning thread %x %i for consts %x %i\n", pth, pth->header.flags, pth->cocache, pth->cachesize);
        for (i = 0; i < pth->cachesize; i++) {
            PObject *co = pth->cocache[i].obj;

            if (co && GCH_FLAG(co) != GC_USED)
                continue;
            //not marked, not staged, not null, not const_marked: remove it
            pth->cocache[i].obj = NULL;
        }
        obj = PNT(pth->next);
    } while (obj != PNT(_vm.thlist));
    debug( ">>>>>>>MARK stopped\n\n\n");

}
Beispiel #7
0
Datei: gc.c Projekt: roby85/Viper
void gc_keep_root(void) {
    PObject *obj;
    int i;

    if (_vmpnt) {
        //get the root set
        obj = PNT(_vm.thlist);
        do {
            PThread *pth = (PThread *)obj;
            VThread vth = pth->th;
            debug( "Scanning thread %x %i\n", pth, pth->header.flags);
            if (vth && vosThGetStatus(vth) == VTHREAD_INACTIVE) {
                //terminated, remove from list...it will die if no references remain
                pth->prev->next = pth->next;
                pth->next->prev = pth->prev;
                GCH_FLAG_SET(pth, GC_USED);
                //free workspace
                //if PThread has references, it's ok. But it can't be restarted
                _gc_free(vth);
                pth->th = NULL;
            } else {
                GC_MARK(pth);
                if (pth->frame) GC_KEEP(pth->frame);
            }
            obj = PNT(pth->next);
        } while (obj != PNT(_vm.thlist));

        for (i = 0; i < _vm.nmodules; i++) {
            PModule *mod = VM_MODULE(i);
            GC_MARK(mod);
            if (PMODULE_IS_LOADED(mod)) {
                GC_KEEP_MANY(mod->globals, mod->nfo.nums.nglobals);
            } else {
                GC_KEEP(mod->nfo.frame);
            }
        }
        //-----> irqs could be modifing irq struct here: no worries
        SYSLOCK();
        //slots & irqstack
        for (i = 0; i < _vm.irqn; i++) {
            GC_KEEP(_vm.irqstack[i].fn);
            GC_KEEP_NOTNULL(_vm.irqstack[i].args);
        }

        for (i = 0; i < EXT_SLOTS; i++) {
            if (_vm.irqslots[0][i].fn) {
                GC_KEEP(_vm.irqslots[0][i].fn);
                GC_KEEP_NOTNULL(_vm.irqslots[0][i].args);
            }
            if (_vm.irqslots[1][i].fn) {
                GC_KEEP(_vm.irqslots[1][i].fn);
                GC_KEEP_NOTNULL(_vm.irqslots[1][i].args);
            }
        }
        if (_vm.irqcur) {
            GC_KEEP(_vm.irqcur->fn);
            GC_KEEP_NOTNULL(_vm.irqcur->args);
        }


        if (_vm.timers) {
            obj = _vm.timers;
            do {
                GC_KEEP(obj);
                obj = (PObject *)((PSysObject *)obj)->sys.timer.next;
            } while (obj != _vm.timers);
        }


        SYSUNLOCK();
        //-----> irq could be modifing irq struct here:
        //       - it can add something to irqslots: np, the objects added must be in an active frame (gc lock is on, no new frame can be created)
        //       - it can add something to irqstack from pin irq: np, the objects are sitting in irqslots
        //       - it can add something to irqstack from timers: that timer was in the timer list, so it is already kept
        //       - it can be the irqthread at 2 different times:
        //           - it modifies _vm.irqcur after putting it in a new frame: if happens up there, np. if happens now, already kept
        //           - it does _vm.irqn--: if happens up there, the removed irqfn is in irqcur. if happens here, already kept
    }

}