static void OptConstants(Proto* tf) { Instruction* p; int n=tf->nknum+tf->nkstr; Hash* map=luaH_new(L,n); int m=MapConstants(tf,map); #ifdef DEBUG printf("%p n=%d m=%d %s\n",tf,n,m,(m==n)?"nothing to optimize":"yes!"); #endif if (m==n) return; for (p=tf->code;; p++) { Instruction i=*p; int op=GET_OPCODE(i); switch (op) { TObject o; int j,k; case OP_PUSHNUM: case OP_PUSHNEGNUM: j=GETARG_U(i); ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j]; k=MapConstant(map,-1,&o); if (k!=j) *p=CREATE_U(op,k); break; case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED: case OP_PUSHSELF: case OP_SETGLOBAL: j=GETARG_U(i); ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j]; k=MapConstant(map,-1,&o); if (k!=j) *p=CREATE_U(op,k); break; case OP_END: PackConstants(tf,map); luaH_free(L,map); return; default: break; } } }
static void freeobj (lua_State *L, GCObject *o) { switch (o->gch.tt) { case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break; case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break; case LUA_TTABLE: luaH_free(L, gcotoh(o)); break; case LUA_TTHREAD: { lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread); luaE_freethread(L, gcototh(o)); break; } case LUA_TSTRING: { luaM_free(L, o, sizestring(gcotots(o)->tsv.len)); break; } case LUA_TUSERDATA: { luaM_free(L, o, sizeudata(gcotou(o)->uv.len)); break; } default: lua_assert(0); } }
static void OptConstants(Proto* tf) { Instruction* p; int n=tf->nknum+tf->nkstr; Hash* map=luaH_new(compile_lua_state,n); int m=MapConstants(tf,map); if (m==n) return; for (p=tf->code;; p++) { Instruction i=*p; int op=GET_OPCODE(i); switch (op) { TObject o; int j,k; case OP_PUSHNUM: case OP_PUSHNEGNUM: j=GETARG_U(i); ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j]; k=MapConstant(map,-1,&o); if (k!=j) *p=CREATE_U(op,k); break; case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED: case OP_PUSHSELF: case OP_SETGLOBAL: j=GETARG_U(i); ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j]; k=MapConstant(map,-1,&o); if (k!=j) *p=CREATE_U(op,k); break; case OP_END: PackConstants(tf,map); luaH_free(compile_lua_state,map); return; default: break; } } }
static void freeobj (lua_State *L, GCObject *o) { switch (o->gch.tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break; case LUA_TTHREAD: { lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); luaE_freethread(L, gco2th(o)); break; } case LUA_TSTRING: { G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; } case LUA_TUSERDATA: { luaM_freemem(L, o, sizeudata(gco2u(o))); break; } default: lua_assert(0); } }
void lua_close (void) { TaggedString *alludata = luaS_collectudata(); L->GCthreshold = MAX_INT; /* to avoid GC during GC */ luaC_hashcallIM((Hash *)L->roottable.next); /* GC t.methods for tables */ luaC_strcallIM(alludata); /* GC tag methods for userdata */ luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ luaH_free((Hash *)L->roottable.next); luaF_freeproto((TProtoFunc *)L->rootproto.next); luaF_freeclosure((Closure *)L->rootcl.next); luaS_free(alludata); luaS_freeall(); luaM_free(L->stack.stack); luaM_free(L->IMtable); luaM_free(L->refArray); luaM_free(L->Mbuffer); luaM_free(L->Cblocks); luaM_free(L); L = NULL; #ifdef DEBUG printf("total de blocos: %ld\n", numblocks); printf("total de memoria: %ld\n", totalmem); #endif }
static void freeobj (lua_State *L, GCObject *o) { switch (gch(o)->tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TLCL: { freeLclosure(L, gco2lcl(o)); break; } case LUA_TCCL: { luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); break; } case LUA_TTABLE: luaH_free(L, gco2t(o)); break; case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; case LUA_TSHRSTR: luaS_remove(L, rawgco2ts(o)); /* remove it from hash table */ /* go through */ case LUA_TLNGSTR: { luaM_freemem(L, o, sizestring(gco2ts(o))); break; } default: lua_assert(0); } }
int32 lua_collectgarbage(int32 limit) { int32 recovered = nblocks; // to subtract nblocks after gc Hash *freetable; TaggedString *freestr; TProtoFunc *freefunc; Closure *freeclos; markall(); invalidaterefs(); freestr = luaS_collector(); freetable = (Hash *)listcollect(&roottable); freefunc = (TProtoFunc *)listcollect(&rootproto); freeclos = (Closure *)listcollect(&rootcl); GCthreshold *= 4; // to avoid GC during GC luaC_hashcallIM(freetable); // GC tag methods for tables luaC_strcallIM(freestr); // GC tag methods for userdata luaD_gcIM(&luaO_nilobject); // GC tag method for nil (signal end of GC) luaH_free(freetable); luaS_free(freestr); luaF_freeproto(freefunc); luaF_freeclosure(freeclos); recovered = recovered - nblocks; GCthreshold = (limit == 0) ? 2 * nblocks : nblocks + limit; return recovered; }
static void cleartable (lua_State *L, GCObject *l) { #else static void cleartable (GCObject *l) { #endif /* LUA_REFCOUNT */ while (l) { Table *h = gco2h(l); int i = h->sizearray; lua_assert(testbit(h->marked, VALUEWEAKBIT) || testbit(h->marked, KEYWEAKBIT)); if (testbit(h->marked, VALUEWEAKBIT)) { while (i--) { TValue *o = &h->array[i]; #if LUA_REFCOUNT if (iscleared(o, 0)) { /* value was collected? */ if (iscollectable(o)) o->value.gc->gch.ref--; setnilvalue2n(l, o); /* remove value */ } #else if (iscleared(o, 0)) /* value was collected? */ setnilvalue(o); /* remove value */ #endif /* LUA_REFCOUNT */ } } i = sizenode(h); while (i--) { Node *n = gnode(h, i); if (!ttisnil(gval(n)) && /* non-empty entry? */ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { #if LUA_REFCOUNT if (iscollectable(gval(n))) gval(n)->value.gc->gch.ref--; setnilvalue2n(L, gval(n)); /* remove value ... */ #else setnilvalue(gval(n)); /* remove value ... */ #endif /* LUA_REFCOUNT */ removeentry(n); /* remove entry from table */ } } l = h->gclist; } } static void freeobj (lua_State *L, GCObject *o) { switch (o->gch.tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break; case LUA_TTHREAD: { lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); luaE_freethread(L, gco2th(o)); break; } case LUA_TSTRING: { G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; } #if LUA_WIDESTRING case LUA_TWSTRING: { G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; } #endif /* LUA_WIDESTRING */ case LUA_TUSERDATA: { luaM_freemem(L, o, sizeudata(gco2u(o))); break; } default: lua_assert(0); } } #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { GCObject *curr; global_State *g = G(L); int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ sweepwholelist(L, &gco2th(curr)->openupval); if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); makewhite(g, curr); /* make it white (for next cycle) */ p = &curr->gch.next; } else { /* must erase `curr' */ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); #if LUA_REFCOUNT if (curr->gch.prev) curr->gch.prev->gch.next = curr->gch.next; if (curr->gch.next) curr->gch.next->gch.prev = (GCObject*)p; #endif /* LUA_REFCOUNT */ *p = curr->gch.next; if (curr == g->rootgc) /* is the first element of the list? */ g->rootgc = curr->gch.next; /* adjust first */ freeobj(L, curr); } } return p; }