static int hasmark (const TObject *o) { /* valid only for locked objects */ switch (o->ttype) { case LUA_TSTRING: case LUA_TUSERDATA: return tsvalue(o)->marked; case LUA_TTABLE: return ismarked(hvalue(o)); case LUA_TFUNCTION: return ismarked(clvalue(o)); default: /* number */ return 1; } }
void print_traverse(value_t v) { value_t *bp; while (iscons(v)) { if (ismarked(v)) { bp = (value_t*)ptrhash_bp(&printconses, (void*)v); if (*bp == (value_t)HT_NOTFOUND) *bp = fixnum(printlabel++); return; } mark_cons(v); print_traverse(car_(v)); v = cdr_(v); } if (!ismanaged(v) || issymbol(v)) return; if (ismarked(v)) { bp = (value_t*)ptrhash_bp(&printconses, (void*)v); if (*bp == (value_t)HT_NOTFOUND) *bp = fixnum(printlabel++); return; } if (isvector(v)) { if (vector_size(v) > 0) mark_cons(v); unsigned int i; for(i=0; i < vector_size(v); i++) print_traverse(vector_elt(v,i)); } else if (iscprim(v)) { mark_cons(v); } else if (isclosure(v)) { mark_cons(v); function_t *f = (function_t*)ptr(v); print_traverse(f->bcode); print_traverse(f->vals); print_traverse(f->env); } else { assert(iscvalue(v)); cvalue_t *cv = (cvalue_t*)ptr(v); // don't consider shared references to "" if (!cv_isstr(cv) || cv_len(cv)!=0) mark_cons(v); fltype_t *t = cv_class(cv); if (t->vtable != NULL && t->vtable->print_traverse != NULL) t->vtable->print_traverse(v); } }
void reallymarkobject (GCState *st, GCObject *o) { lua_assert(!ismarked(o)); setbit(o->gch.marked, 0); /* mark object */ switch (o->gch.tt) { case LUA_TUSERDATA: { markvalue(st, gcotou(o)->uv.metatable); break; } case LUA_TFUNCTION: { gcotocl(o)->c.gclist = st->tmark; st->tmark = o; break; } case LUA_TTABLE: { gcotoh(o)->gclist = st->tmark; st->tmark = o; break; } case LUA_TTHREAD: { #if LUA_REFCOUNT gcototh(o)->gclist_head.next = st->tmark; #else !LUA_REFCOUNT gcototh(o)->gclist = st->tmark; #endif LUA_REFCOUNT st->tmark = o; break; } case LUA_TPROTO: { gcotop(o)->gclist = st->tmark; st->tmark = o; break; } default: lua_assert(o->gch.tt == LUA_TSTRING || o->gch.tt == LUA_TWSTRING); } }
/* move `dead' udata that need finalization to list `tmudata' */ size_t luaC_separateudata (lua_State *L) { size_t deadmem = 0; GCObject **p = &G(L)->rootudata; GCObject *curr; GCObject *collected = NULL; /* to collect udata with gc event */ GCObject **lastcollected = &collected; while ((curr = *p) != NULL) { lua_assert(curr->gch.tt == LUA_TUSERDATA); if (ismarked(curr) || isfinalized(gcotou(curr))) p = &curr->gch.next; /* don't bother with them */ else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { markfinalized(gcotou(curr)); /* don't need finalization */ p = &curr->gch.next; } else { /* must call its gc method */ deadmem += sizeudata(gcotou(curr)->uv.len); *p = curr->gch.next; curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ *lastcollected = curr; lastcollected = &curr->gch.next; } } /* insert collected udata with gc event into `tmudata' list */ *lastcollected = G(L)->tmudata; G(L)->tmudata = collected; return deadmem; }
static int print_circle_prefix(ios_t *f, value_t v) { value_t label; char buf[64]; char *str; if ((label=(value_t)ptrhash_get(&printconses, (void*)v)) != (value_t)HT_NOTFOUND) { if (!ismarked(v)) { //HPOS+=ios_printf(f, "#%ld#", numval(label)); outc('#', f); str = uint2str(buf, sizeof(buf)-1, numval(label), 10); outs(str, f); outc('#', f); return 1; } //HPOS+=ios_printf(f, "#%ld=", numval(label)); outc('#', f); str = uint2str(buf, sizeof(buf)-1, numval(label), 10); outs(str, f); outc('=', f); } if (ismanaged(v)) unmark_cons(v); return 0; }
static void invalidaterefs (void) { int32 i; for (i=0; i<L->refSize; i++) if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o)) L->refArray[i].status = COLLECTED; }
static void markclosure (GCState *st, Closure *cl) { if (!ismarked(cl)) { if (!cl->isC) protomark(cl->f.l); cl->mark = st->cmark; /* chain it for later traversal */ st->cmark = cl; } }
static void collecttable (lua_State *L) { Hash **p = &L->roottable; Hash *next; while ((next = *p) != NULL) { if (ismarked(next)) { next->mark = next; /* unmark */ p = &next->next; } else { *p = next->next; luaH_free(L, next); } } }
static void collectclosure (lua_State *L) { Closure **p = &L->rootcl; Closure *next; while ((next = *p) != NULL) { if (ismarked(next)) { next->mark = next; /* unmark */ p = &next->next; } else { *p = next->next; luaF_freeclosure(L, next); } } }
vector<hvec> trace(hvec stpoint) /* Traces a contour. The start point, because of the way the iteration works, * is the leftmost point of the bottom line, so it starts going right. */ {hvec dir(1), left(1,1), right(0,-1); vector<hvec> contour; while (isedge(stpoint) && !ismarked(stpoint)) {contour.push_back(stpoint); mark(stpoint); if (isedge(stpoint+dir)) ; else if (isedge(stpoint+dir*left)) dir*=left; else dir*=right; stpoint+=dir; } return contour; }
static const void * readobject(lua_State *L, lua_State *dL, const void *parent, const char *desc) { int t = lua_type(L, -1); int tidx = 0; const void * p = NULL; switch (t) { case LUA_TTABLE: tidx = TABLE; break; case LUA_TFUNCTION: tidx = FUNCTION; break; case LUA_TTHREAD: tidx = THREAD; break; case LUA_TUSERDATA: tidx = USERDATA; break; default: return NULL; } p = lua_topointer(L, -1); if (ismarked(dL, p)) { lua_rawgetp(dL, tidx, p); if (!lua_isnil(dL,-1)) { lua_pushstring(dL,desc); lua_rawsetp(dL, -2, parent); } lua_pop(dL,1); lua_pop(L,1); return NULL; } lua_newtable(dL); lua_pushstring(dL,desc); lua_rawsetp(dL, -2, parent); lua_rawsetp(dL, tidx, p); return p; }
static void markobject (GCState *st, TObject *o) { switch (ttype(o)) { case LUA_TUSERDATA: case LUA_TSTRING: strmark(tsvalue(o)); break; case LUA_TMARK: markclosure(st, infovalue(o)->func); break; case LUA_TFUNCTION: markclosure(st, clvalue(o)); break; case LUA_TTABLE: { if (!ismarked(hvalue(o))) { hvalue(o)->mark = st->tmark; /* chain it in list of marked */ st->tmark = hvalue(o); } break; } default: break; /* numbers, etc */ } }
static void marktmu (GCState *st) { GCObject *u; #if LUA_REFCOUNT for (u = st->g->tmudata_head.next; u != (GCObject*)&st->g->tmudata_tail; u = u->gch.next) { #else !LUA_REFCOUNT for (u = st->g->tmudata; u; u = u->gch.next) { #endif LUA_REFCOUNT unmark(u); /* may be marked, if left from previous GC */ reallymarkobject(st, u); } } /* move `dead' udata that need finalization to list `tmudata' */ size_t luaC_separateudata (lua_State *L) { size_t deadmem = 0; #if LUA_REFCOUNT GCObject **p = &G(L)->rootudata_head.next; #else !LUA_REFCOUNT GCObject **p = &G(L)->rootudata; #endif LUA_REFCOUNT GCObject *curr; GCObject *collected = NULL; /* to collect udata with gc event */ #if !LUA_REFCOUNT GCObject **lastcollected = &collected; while ((curr = *p) != NULL) { lua_assert(curr->gch.tt == LUA_TUSERDATA); #else LUA_REFCOUNT while ((curr = *p) != (GCObject*)&G(L)->rootudata_tail) { #endif LUA_REFCOUNT if (ismarked(curr) || isfinalized(gcotou(curr))) p = &curr->gch.next; /* don't bother with them */ else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { markfinalized(gcotou(curr)); /* don't need finalization */ p = &curr->gch.next; } else { /* must call its gc method */ deadmem += sizeudata(gcotou(curr)->uv.len); *p = curr->gch.next; #if LUA_REFCOUNT Unlink(curr); curr->gch.next = (GCObject*)&G(L)->tmudata_tail; /* link `curr' at the end of `collected' list */ curr->gch.prev = G(L)->tmudata_tail.prev; G(L)->tmudata_tail.prev->gch.next = curr; G(L)->tmudata_tail.prev = curr; #else !LUA_REFCOUNT curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ *lastcollected = curr; lastcollected = &curr->gch.next; #endif LUA_REFCOUNT } } /* insert collected udata with gc event into `tmudata' list */ #if LUA_REFCOUNT // *lastcollected = G(L)->tmudata_head.next; // G(L)->tmudata_head.next = collected; #else !LUA_REFCOUNT *lastcollected = G(L)->tmudata; G(L)->tmudata = collected; #endif LUA_REFCOUNT return deadmem; } static void removekey (lua_State *L, Node *n) { (void)L; setnilvalue(gval(n)); /* remove corresponding value ... */ if (iscollectable(gkey(n))) setttype(gkey(n), LUA_TNONE); /* dead key; remove it */ }
static void invalidaterefs() { int32 i; for (i = 0; i < refSize; i++) if (refArray[i].status == HOLD && !ismarked(&refArray[i].o)) refArray[i].status = COLLECTED; }
/* mark all the nodes in the hat file that are reachable * from the given root -- setting the highest bit in the * tag byte */ void markfrom (FileOffset root, FileOffset *buf) { char tag; if (root > 8 && root < filesize) { /* First read the tag byte. If it is marked, return. * If it is not marked, then mark it now. */ fseek(f,(long int)root,SEEK_SET); fread(&tag,sizeof(char),1,f); if (ismarked(tag)) return; marktag(&tag); fseek(f,(long int)root,SEEK_SET); fwrite(&tag,sizeof(char),1,f); cleartag(&tag); /* Examine the tag to determine the kind of node. * Read pointers from the node into buf, then * markfrom() these pointers recursively. The buffer is * overwritten where possible to minimise the risk of overflow: * for this reason, pointers are recursively traced in * reverse order. */ { int k = lo5(tag); if ((ExpDoStmt < k && k < AtomVariable) || k > ListCons) { fprintf(stderr, "strange tag %d at 0x%x\n", k, root); exit(1); } switch (k) { case ListCons: fread(buf,sizeof(FileOffset),2,f); /* two pointers */ markfrom(getpointer(buf+1),buf+1); markfrom(getpointer(buf),buf); break; case Module: break; case AtomAbstract: break; case SrcPos: case AtomVariable: case AtomConstructor: /* ignore fieldnames for now */ fread(buf,sizeof(FileOffset),1,f); /* points to module mode */ markfrom(getpointer(buf),buf); break; default: { int pos = 0; if (hasSrcPos(tag)) { fread(buf+pos,sizeof(FileOffset),1,f); pos++; } fread(buf+pos,sizeof(FileOffset),1,f); /* parent pointer */ pos++; switch (k) { case ExpApp: fread(buf+pos,sizeof(FileOffset),2,f); /* result+fun */ pos += 2; { unsigned char arity; fread(&arity,sizeof(unsigned char),1,f); fread(buf+pos,sizeof(FileOffset),(unsigned int)arity,f); pos += (int)arity; } break; case ExpValueApp: fread(buf+pos,sizeof(FileOffset),1,f); /* fun */ pos += 1; { unsigned char arity; fread(&arity,sizeof(unsigned char),1,f); fread(buf+pos,sizeof(FileOffset),(unsigned int)arity,f); pos += (int)arity; } break; case ExpValueUse: case ExpConstUse: case ExpProjection: fread(buf+pos,sizeof(FileOffset),1,f); /* one extra pointer */ pos++; break; case ExpHidden: case ExpConstDef: case ExpFieldUpdate: /* ignore fieldnames for now */ case ExpGuard: case ExpCase: case ExpIf: fread(buf+pos,sizeof(FileOffset),2,f); /* two pointers */ pos+=2; break; default: break; /* no pointers */ } for (;pos-->0;) markfrom(getpointer(buf+pos), buf+pos); } break; } } } }
void nextnode (void) { FileOffset offset = nextoffset; char b; int marked, err; err = fread(&b,sizeof(char),1,f); nextoffset+=1; if (err!=1) return; if (rmode || xmode) { marked = ismarked(b); if (marked) { cleartag(&b); newtagat(&b, offset); } if (amode) printf("%s", (marked ? "=> " : " ")); } { int k = lo5(b); if ((ExpDoStmt<k && k<AtomVariable) || k>ListCons) { fprintf(stderr, "strange tag %d at byte offset 0x%x\n", k, offset); exit(1); } else if (smode) { count[k]++; if (rmode && marked) reachcount[k]++; } switch (k) { case ListCons: if (gmode) printf("%d [label=\"0x%x ListCons\"]\n", offset, offset); if (amode) printf("0x%x: %-20s\t", offset, tag2str(k)); if (amode) printf("elem="); dopointer(NONZERO, ANYEXP, readpointer(), k, offset, "e"); if (amode) printf(" tail="); dopointer(MAYBEZERO, ListCons, readpointer(), k, offset, "t"); break; case Module: if (amode) { if (tracedModule(b)) printf("0x%x: Module (suspect) \t", offset); else printf("0x%x: Module (trusted) \t", offset); } { char *s = readstring(); if (amode) printf("%s\t", s); } { char *s = readstring(); if (amode) printf("\"%s\"", s); } break; case SrcPos: if (amode) printf("0x%x: SrcPos\t\t\t", offset); dopointer(NONZERO, Module, readpointer(), k, offset, ""); { char *p = readposn(); if (amode) printf(" %s", p); } break; case AtomVariable: if (amode) { if (localDef(b)) printf("0x%x: AtomVariable (local)\t", offset); else printf("0x%x: AtomVariable (toplevel)\t", offset); } if (gmode) printf("%d [label=\"0x%x AtomVariable", offset, offset); dopointer(NONZERO, Module, readpointer(), k, offset, ""); { char *p = readposn(); if (amode) printf(" %s", p); } { char *fp = readfixpri(); if (*fp!='\0' && amode) printf("%s ", fp); } { unsigned int a = readarity(); if (amode || gmode) printf(amode ? " arity=%u," : " %u", a); } { char *n = readstring(); if (amode || gmode) printf(" %s", n); } if (gmode) printf("\"]\n"); break; case AtomConstructor: if (amode) printf("0x%x: %-20s\t", offset, tag2str(k)); if (gmode) printf("%d [label=\"0x%x AtomConstructor", offset, offset); dopointer(NONZERO, Module, readpointer(), k, offset, ""); { char *p = readposn(); if (amode) printf(" %s", p); } { char *fp = readfixpri(); if (*fp!='\0' && amode) printf("%s", fp); } { unsigned int a = readarity(); if (amode || gmode) printf(amode ? " arity=%u," : " %u", a); { char *n = readstring(); if (amode || gmode) printf(" %s", n); } if (gmode) printf("\"]\n"); if hasFields(b) { int i; if (amode) printf(" fields:"); for (i=1; i<=a; i++) { dopointer(NONZERO, AtomVariable, readpointer(), k, offset, (gmode ? (sprintf(stringbuf,"%d",i), stringbuf) : "") ); } } } break; case AtomAbstract: if (amode) printf("0x%x: %-20s\t", offset, tag2str(k)); if (gmode) printf("%d [label=\"0x%x AtomAbstract ", offset, offset); { char *s = readstring(); if (amode || gmode) printf("%s", s); } if (gmode) printf("\"]\n"); break; default: { if (amode) printf("0x%x: %-20s\t", offset, tag2str(k)); if (hasSrcPos(b)) { if (amode) printf("use="); dopointer(NONZERO, SrcPos, readpointer(), k, offset, ""); if (amode) printf(" "); } // if (amode && (ExpChar <= k) && (k <= ExpConstUse)) { // printf("("); // if (!isEntered(b)) printf("not "); // printf("entered) "); // } switch (k) { case ExpApp: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" result="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "r"); if (amode) printf(" fun="); dopointer(NONZERO, ANYEXP, readpointer(), k, offset, "f"); if (gmode) printf("%d [label=\"0x%x ExpApp", offset, offset); { unsigned int a = readarity(); int i; if (amode || gmode) printf(amode ? " arity=%u, args " : " %u\"]\n",a); for (i=1; i<=a; i++) dopointer(NONZERO, ANYEXP, readpointer(), k, offset, (gmode ? (sprintf(stringbuf,"%d",i), stringbuf) : "") ); } break; case ExpValueApp: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" fun="); dopointer(NONZERO, ANYATOM, readpointer(), k, offset, "f"); if (gmode) printf("%d [label=\"0x%x ExpValueApp", offset, offset); { unsigned int a = readarity(); int i; if (amode || gmode) printf(amode ? " arity=%u, args " : " %u\"]\n",a); for (i=1; i<=a; i++) dopointer(NONZERO, ANYEXP, readpointer(), k, offset, (gmode ? (sprintf(stringbuf,"%d",i), stringbuf) : "") ); } break; case ExpChar: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); { char c = nextbyte(); if (gmode) printf("%d [label=\"ExpChar", offset); if (amode || gmode) printf(" '%c'", c); if (gmode) printf("\"]\n"); } break; case ExpInt: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); { int i; i = readfourbytes(); if (gmode) printf("%d [label=\"ExpInt", offset); if (amode || gmode) printf(" %d", i); if (gmode) printf("\"]\n"); } break; case ExpInteger: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); { char* i; i = readinteger(); if (gmode) printf("%d [label=\"ExpInteger", offset); if (amode || gmode) printf(" %s", i); if (gmode) printf("\"]\n"); } break; case ExpRat: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); { int n,d; n=readfourbytes(); d=readfourbytes(); if (gmode) printf("%d [label=\"ExpRat", offset); if (amode || gmode) printf(" %d%%%d", n,d); if (gmode) printf("\"]\n"); } break; case ExpRational: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); { char* r = readrational(); if (gmode) printf("%d [label=\"ExpRational", offset); if (amode || gmode) printf(" %s", r); if (gmode) printf("\"]\n"); } break; case ExpFloat: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); { float f = readfloat(); if (gmode) printf("%d [label=\"ExpFloat", offset); if (amode || gmode) printf(" %f", f); if (gmode) printf("\"]\n"); } break; case ExpDouble: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); { double d = readdouble(); if (gmode) printf("%d [label=\"ExpDouble", offset); if (amode || gmode) printf(" %f", d); if (gmode) printf("\"]\n"); } break; case ExpValueUse: if (gmode) printf("%d [label=\"0x%x ExpValueUse\"]\n", offset, offset); if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" value="); dopointer(MAYBELAMBDA, ANYATOM, readpointer(), ExpValueUse, offset,"v"); break; case ExpConstUse: if (gmode) printf("%d [label=\"0x%x ExpConstUse\"]\n", offset, offset); if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" const="); dopointer(NONZERO, ExpConstDef, readpointer(), k, offset, "c"); break; case ExpConstDef: if (gmode) printf("%d [label=\"0x%x ExpConstDef\"]\n", offset, offset); if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" result="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "r"); if (amode) printf(" var="); dopointer(NONZERO, AtomVariable, readpointer(), k, offset, "v"); break; case ExpGuard: case ExpCase: case ExpIf: if (gmode) printf("%d [label=\"0x%x %s\"]\n", offset, offset, k==ExpGuard ? "ExpGuard" : k==ExpCase ? "ExpCase" : "ExpIf"); if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" result="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "r"); if (amode) printf(" cond="); dopointer(NONZERO, ANYEXP, readpointer(), k, offset, "c"); break; case ExpFieldUpdate: if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" result="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "r"); if (amode) printf(" arg="); dopointer(NONZERO, ANYEXP, readpointer(), k, offset, "a"); { unsigned int i, arity = readarity(); if (gmode) printf("%d [label=\"0x%x ExpFieldUpdate %u\"]\n", offset, offset, arity); if (amode) printf(" arity=%u, binders ",arity); for (i=0; i<arity; i++) { dopointer(NONZERO, AtomVariable, readpointer(), k, offset, ""); } if (amode) printf(", bindees ",arity); for (i=0; i<arity; i++) { dopointer(NONZERO, ANYEXP, readpointer(), k, offset, ""); } } break; case ExpProjection: if (gmode) printf("%d [label=\"0x%x ExpProjection\"]\n", offset, offset); if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" exp="); dopointer(NONZERO, ANYEXP, readpointer(), k, offset, "e"); break; case ExpHidden: if (gmode) printf("%d [label=\"0x%x ExpHidden\"]\n", offset, offset); if (amode) printf("parent="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "p"); if (amode) printf(" result="); dopointer(MAYBEZERO, ANYEXP, readpointer(), k, offset, "r"); if (amode) printf(" children="); dopointer(MAYBEZERO, ListCons, readpointer(), k, offset, "c"); break; case ExpForward: if (gmode) printf("%d [label=\"0x%x ExpForward\"]\n", offset, offset); if (amode) printf("result="); dopointer(NONZERO, ANYEXP, readpointer(), k, offset, "r"); break; case ExpDoStmt: if (gmode) printf("%d [label=\"0x%x ExpDoStmt\"]\n", offset, offset); if (amode) printf("stmt="); dopointer(NONZERO, ANYEXP, readpointer(), k, offset, "s"); break; } }} if (amode) printf("\n"); if (smode) space[k] += nextoffset - offset; } }