ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

lgc.cpp

Go to the documentation of this file.
00001 /*
00002 ** Garbage Collector
00003 ** See Copyright Notice in lua.h
00004 */
00005 
00006 #define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
00007 #define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
00008 
00009 #include "engines/grim/lua/ldo.h"
00010 #include "engines/grim/lua/lfunc.h"
00011 #include "engines/grim/lua/lgc.h"
00012 #include "engines/grim/lua/lmem.h"
00013 #include "engines/grim/lua/lobject.h"
00014 #include "engines/grim/lua/lstate.h"
00015 #include "engines/grim/lua/lstring.h"
00016 #include "engines/grim/lua/ltable.h"
00017 #include "engines/grim/lua/ltm.h"
00018 #include "engines/grim/lua/lua.h"
00019 
00020 namespace Grim {
00021 
00022 static int32 markobject (TObject *o);
00023 
00024 /*
00025 ** =======================================================
00026 ** REF mechanism
00027 ** =======================================================
00028 */
00029 
00030 int32 luaC_ref(TObject *o, int32 lock) {
00031     int32 ref;
00032     if (ttype(o) == LUA_T_NIL)
00033         ref = -1;   // special ref for nil
00034     else {
00035         for (ref = 0; ref < refSize; ref++)
00036             if (refArray[ref].status == FREE)
00037                 goto found;
00038         // no more empty spaces
00039         {
00040             int32 oldSize = refSize;
00041             refSize = luaM_growvector(&refArray, refSize, struct ref, refEM, MAX_WORD);
00042             for (ref = oldSize; ref < refSize; ref++) {
00043                 refArray[ref].status = FREE;
00044                 refArray[ref].o.ttype = LUA_T_NIL;
00045                 refArray[ref].o.value.ts = nullptr;
00046             }
00047             ref = oldSize;
00048         }
00049 found:
00050         refArray[ref].o = *o;
00051         refArray[ref].status = lock ? LOCK : HOLD;
00052     }
00053     return ref;
00054 }
00055 
00056 void lua_unref(int32 r) {
00057     if (r >= 0 && r < refSize) {
00058         refArray[r].status = FREE;
00059         refArray[r].o.ttype = LUA_T_NIL;
00060         refArray[r].o.value.ts = nullptr;
00061     }
00062 }
00063 
00064 TObject* luaC_getref(int32 r) {
00065     if (r == -1)
00066         return &luaO_nilobject;
00067     if (r >= 0 && r < refSize && (refArray[r].status == LOCK || refArray[r].status == HOLD))
00068         return &refArray[r].o;
00069     else
00070         return nullptr;
00071 }
00072 
00073 static void travlock() {
00074     int32 i;
00075     for (i = 0; i < refSize; i++) {
00076         if (refArray[i].status == LOCK) {
00077             markobject(&refArray[i].o);
00078         }
00079     }
00080 }
00081 
00082 static int32 ismarked(TObject *o) {
00083     // valid only for locked objects
00084     switch (o->ttype) {
00085     case LUA_T_STRING:
00086         return o->value.ts->head.marked;
00087     case LUA_T_ARRAY:
00088         return o->value.a->head.marked;
00089     case LUA_T_CLOSURE:
00090         return o->value.cl->head.marked;
00091     case LUA_T_PROTO:
00092         return o->value.tf->head.marked;
00093 #ifdef LUA_DEBUG
00094     case LUA_T_LINE:
00095     case LUA_T_CLMARK:
00096     case LUA_T_CMARK:
00097     case LUA_T_PMARK:
00098         LUA_INTERNALERROR("internal error");
00099 #endif
00100     default:  // nil, number or cproto
00101         return 1;
00102     }
00103 }
00104 
00105 static void invalidaterefs() {
00106     int32 i;
00107     for (i = 0; i < refSize; i++)
00108         if (refArray[i].status == HOLD && !ismarked(&refArray[i].o))
00109             refArray[i].status = COLLECTED;
00110 }
00111 
00112 void luaC_hashcallIM(Hash *l) {
00113     TObject t;
00114     ttype(&t) = LUA_T_ARRAY;
00115     for (; l; l = (Hash *)l->head.next) {
00116         avalue(&t) = l;
00117         luaD_gcIM(&t);
00118     }
00119 }
00120 
00121 void luaC_strcallIM(TaggedString *l) {
00122     TObject o;
00123     ttype(&o) = LUA_T_USERDATA;
00124     for (; l; l=(TaggedString *)l->head.next) {
00125         if (l->constindex == -1) {  // is userdata?
00126             tsvalue(&o) = l;
00127             luaD_gcIM(&o);
00128         }
00129     }
00130 }
00131 
00132 static GCnode *listcollect(GCnode *l) {
00133     GCnode *frees = nullptr;
00134     while (l) {
00135         GCnode *next = l->next;
00136         l->marked = 0;
00137         while (next && !next->marked) {
00138             l->next = next->next;
00139             next->next = frees;
00140             frees = next;
00141             next = l->next;
00142         }
00143         l = next;
00144     }
00145     return frees;
00146 }
00147 
00148 static void strmark(TaggedString *s) {
00149     if (!s->head.marked)
00150         s->head.marked = 1;
00151 }
00152 
00153 static void protomark(TProtoFunc *f) {
00154     if (!f->head.marked) {
00155         LocVar *v = f->locvars;
00156         int32 i;
00157         f->head.marked = 1;
00158         if (f->fileName)
00159             strmark(f->fileName);
00160         for (i = 0; i < f->nconsts; i++)
00161             markobject(&f->consts[i]);
00162         if (v) {
00163             for (; v->line != -1; v++) {
00164                 if (v->varname)
00165                     strmark(v->varname);
00166             }
00167         }
00168     }
00169 }
00170 
00171 static void closuremark(Closure *f) {
00172     if (!f->head.marked) {
00173         int32 i;
00174         f->head.marked = 1;
00175         for (i = f->nelems; i >= 0; i--)
00176             markobject(&f->consts[i]);
00177     }
00178 }
00179 
00180 static void hashmark(Hash *h) {
00181     if (!h->head.marked) {
00182         int32 i;
00183         h->head.marked = 1;
00184         for (i = 0; i < nhash(h); i++) {
00185             Node *n = node(h, i);
00186             if (ttype(ref(n)) != LUA_T_NIL) {
00187                 markobject(&n->ref);
00188                 markobject(&n->val);
00189             }
00190         }
00191     }
00192 }
00193 
00194 static void globalmark() {
00195     TaggedString *g;
00196     for (g = (TaggedString *)rootglobal.next; g; g = (TaggedString *)g->head.next){
00197         if (g->globalval.ttype != LUA_T_NIL) {
00198             markobject(&g->globalval);
00199             strmark(g);  // cannot collect non nil global variables
00200         }
00201     }
00202 }
00203 
00204 static int32 markobject(TObject *o) {
00205     switch (ttype(o)) {
00206     case LUA_T_STRING:
00207         strmark(tsvalue(o));
00208         break;
00209     case LUA_T_ARRAY:
00210         hashmark(avalue(o));
00211         break;
00212     case LUA_T_CLOSURE:
00213     case LUA_T_CLMARK:
00214         closuremark(o->value.cl);
00215         break;
00216     case LUA_T_PROTO:
00217     case LUA_T_PMARK:
00218         protomark(o->value.tf);
00219         break;
00220     default:
00221         break;  // numbers, cprotos, etc
00222     }
00223     return 0;
00224 }
00225 
00226 static void markall() {
00227     luaD_travstack(markobject); // mark stack objects
00228     globalmark();  // mark global variable values and names
00229     travlock(); // mark locked objects
00230     luaT_travtagmethods(markobject);  // mark fallbacks
00231 }
00232 
00233 int32 lua_collectgarbage(int32 limit) {
00234     int32 recovered = nblocks;  // to subtract nblocks after gc
00235     Hash *freetable;
00236     TaggedString *freestr;
00237     TProtoFunc *freefunc;
00238     Closure *freeclos;
00239     markall();
00240     invalidaterefs();
00241     freestr = luaS_collector();
00242     freetable = (Hash *)listcollect(&roottable);
00243     freefunc = (TProtoFunc *)listcollect(&rootproto);
00244     freeclos = (Closure *)listcollect(&rootcl);
00245     GCthreshold *= 4;  // to avoid GC during GC
00246     luaC_hashcallIM(freetable);  // GC tag methods for tables
00247     luaC_strcallIM(freestr);  // GC tag methods for userdata
00248     luaD_gcIM(&luaO_nilobject);  // GC tag method for nil (signal end of GC)
00249     luaH_free(freetable);
00250     luaS_free(freestr);
00251     luaF_freeproto(freefunc);
00252     luaF_freeclosure(freeclos);
00253     recovered = recovered - nblocks;
00254     GCthreshold = (limit == 0) ? 2 * nblocks : nblocks + limit;
00255     return recovered;
00256 }
00257 
00258 void luaC_checkGC() {
00259     if (nblocks >= GCthreshold)
00260         lua_collectgarbage(0);
00261 }
00262 
00263 } // end of namespace Grim


Generated on Sat May 25 2019 05:00:48 for ResidualVM by doxygen 1.7.1
curved edge   curved edge