Example #1
0
File: gc.c Project: 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

        }
    }
}
Example #2
0
void *potion_mark_major(Potion *P, const struct PNObject *ptr) {
  struct PNMemory *M = P->mem;
  PN_SIZE i;
  PN_SIZE sz = 16;

  switch (((struct PNFwd *)ptr)->fwd) {
    case POTION_COPIED:
    case POTION_FWD:
      GC_MAJOR_UPDATE(((struct PNFwd *)ptr)->ptr);
    goto done;
  }

  if (ptr->vt > PN_TUSER) {
    GC_MAJOR_UPDATE(PN_VTABLE(ptr->vt));
    int ivars = ((struct PNVtable *)PN_VTABLE(ptr->vt))->ivlen;
    for (i = 0; i < ivars; i++)
      GC_MAJOR_UPDATE(((struct PNObject *)ptr)->ivars[i]);
    goto done;
  }

  switch (ptr->vt) {
    case PN_TWEAK:
      GC_MAJOR_UPDATE(((struct PNWeakRef *)ptr)->data);
    break;
    case PN_TCLOSURE:
      GC_MAJOR_UPDATE(((struct PNClosure *)ptr)->sig);
      for (i = 0; i < ((struct PNClosure *)ptr)->extra; i++)
        GC_MAJOR_UPDATE(((struct PNClosure *)ptr)->data[i]);
    break;
    case PN_TTUPLE: {
      struct PNTuple * volatile t = (struct PNTuple *)potion_fwd((PN)ptr);
      for (i = 0; i < t->len; i++)
        GC_MAJOR_UPDATE(t->set[i]);
    }
    break;
    case PN_TSTATE:
      GC_MAJOR_UPDATE(((Potion *)ptr)->strings);
      GC_MAJOR_UPDATE(((Potion *)ptr)->lobby);
      GC_MAJOR_UPDATE(((Potion *)ptr)->vts);
      GC_MAJOR_UPDATE(((Potion *)ptr)->source);
      GC_MAJOR_UPDATE(((Potion *)ptr)->input);
      GC_MAJOR_UPDATE(((Potion *)ptr)->pbuf);
      GC_MAJOR_UPDATE(((Potion *)ptr)->unclosed);
      GC_MAJOR_UPDATE(((Potion *)ptr)->call);
      GC_MAJOR_UPDATE(((Potion *)ptr)->callset);
    break;
    case PN_TFILE:
      GC_MAJOR_UPDATE(((struct PNFile *)ptr)->path);
    break;
    case PN_TVTABLE:
      GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->parent);
      GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->ivars);
      GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->methods);
      GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->ctor);
      GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->call);
      GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->callset);
    break;
    case PN_TSOURCE:
      GC_MAJOR_UPDATE(((struct PNSource *)ptr)->a[0]);
      GC_MAJOR_UPDATE(((struct PNSource *)ptr)->a[1]);
      GC_MAJOR_UPDATE(((struct PNSource *)ptr)->a[2]);
    break;
    case PN_TPROTO:
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->source);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->sig);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->stack);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->paths);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->locals);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->upvals);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->values);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->protos);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->tree);
      GC_MAJOR_UPDATE(((struct PNProto *)ptr)->asmb);
    break;
    case PN_TTABLE:
      GC_MAJOR_UPDATE_TABLE(PN, (struct PNTable *)potion_fwd((PN)ptr), 1);
    break;
    case PN_TFLEX:
      for (i = 0; i < PN_FLEX_SIZE(ptr); i++)
        GC_MAJOR_UPDATE(PN_FLEX_AT(ptr, i));
    break;
    case PN_TCONT:
      GC_KEEP(ptr);
      pngc_mark_array(P, (_PN *)((struct PNCont *)ptr)->stack + 3, ((struct PNCont *)ptr)->len - 3, 2);
    break;
  }

done:
  sz = potion_type_size(P, ptr);
  return (void *)((char *)ptr + sz);
}
Example #3
0
File: gc.c Project: 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");

}
Example #4
0
File: gc.c Project: 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
    }

}