/* ** table.c ** Module to control static tables */ char *rcs_table="$Id: table.c,v 2.73 1997/07/07 16:44:26 roberto Exp roberto $"; #include "luamem.h" #include "auxlib.h" #include "func.h" #include "opcode.h" #include "tree.h" #include "hash.h" #include "table.h" #include "inout.h" #include "lua.h" #include "fallback.h" #include "luadebug.h" #define BUFFER_BLOCK 256 Symbol *lua_table = NULL; Word lua_ntable = 0; static Long lua_maxsymbol = 0; #define GARBAGE_BLOCK 100 static TaggedString *luaI_createfixedstring (char *name) { TaggedString *ts = luaI_createstring(name); luaI_fixstring(ts); return ts; } void luaI_initsymbol (void) { lua_maxsymbol = BUFFER_BLOCK; lua_table = newvector(lua_maxsymbol, Symbol); luaI_predefine(); } void luaI_initconstant (void) { /* pre-register mem error messages, to avoid loop when error arises */ luaI_createfixedstring(tableEM); luaI_createfixedstring(memEM); } /* ** Given a name, search it at symbol table and return its index. If not ** found, allocate it. */ Word luaI_findsymbol (TaggedString *t) { if (t->u.s.varindex == NOT_USED) { if (lua_ntable == lua_maxsymbol) lua_maxsymbol = growvector(&lua_table, lua_maxsymbol, Symbol, symbolEM, MAX_WORD); t->u.s.varindex = lua_ntable; lua_table[lua_ntable].varname = t; s_ttype(lua_ntable) = LUA_T_NIL; lua_ntable++; } return t->u.s.varindex; } Word luaI_findsymbolbyname (char *name) { return luaI_findsymbol(luaI_createfixedstring(name)); } void luaI_releasestring (TaggedString *t) { if (t->marked == 2) /* string has temporary mark? */ t->marked = 0; } void luaI_fixstring (TaggedString *t) { if (t->marked < 3) t->marked = 3; /* avoid GC */ } TaggedString *luaI_createtempstring (char *name) { TaggedString *ts = luaI_createstring(name); if (!ts->marked) ts->marked = 2; /* avoid (temporarily) GC */ return ts; } int luaI_globaldefined (char *name) { return ttype(&lua_table[luaI_findsymbolbyname(name)].object) != LUA_T_NIL; } /* ** Traverse symbol table objects */ static char *lua_travsymbol (int (*fn)(TObject *)) { Word i; for (i=0; istr; return NULL; } int lua_markobject (TObject *o) {/* if already marked, does not change mark value */ if (ttype(o) == LUA_T_USERDATA || (ttype(o) == LUA_T_STRING && !tsvalue(o)->marked)) tsvalue(o)->marked = 1; else if (ttype(o) == LUA_T_ARRAY) lua_hashmark (avalue(o)); else if ((o->ttype == LUA_T_FUNCTION || o->ttype == LUA_T_MARK) && !o->value.tf->marked) luaI_funcmark(o->value.tf); return 0; } /* * returns 0 if the object is going to be (garbage) collected */ int luaI_ismarked (TObject *o) { switch (o->ttype) { case LUA_T_STRING: case LUA_T_USERDATA: return o->value.ts->marked; case LUA_T_FUNCTION: return o->value.tf->marked; case LUA_T_ARRAY: return o->value.a->mark; default: /* nil, number, cfunction, or user data */ return 1; } } static void call_nilIM (void) { /* signals end of garbage collection */ TObject t; ttype(&t) = LUA_T_NIL; luaI_gcIM(&t); /* end of list */ } /* ** Garbage collection. ** Delete all unused strings and arrays. */ static long gc_block = GARBAGE_BLOCK; static long gc_nentity = 0; /* total of strings, arrays, etc */ static void markall (void) { lua_travstack(lua_markobject); /* mark stack objects */ lua_travsymbol(lua_markobject); /* mark symbol table objects */ luaI_travlock(lua_markobject); /* mark locked objects */ luaI_travfallbacks(lua_markobject); /* mark fallbacks */ } long lua_collectgarbage (long limit) { long recovered = 0; Hash *freetable; TaggedString *freestr; TFunc *freefunc; markall(); luaI_invalidaterefs(); freetable = luaI_hashcollector(&recovered); freestr = luaI_strcollector(&recovered); freefunc = luaI_funccollector(&recovered); gc_nentity -= recovered; gc_block = (limit == 0) ? 2*(gc_block-recovered) : gc_nentity+limit; luaI_hashcallIM(freetable); luaI_strcallIM(freestr); call_nilIM(); luaI_hashfree(freetable); luaI_strfree(freestr); luaI_funcfree(freefunc); /*printf("total %d coletados %d\n", (int)gc_nentity, (int)recovered);*/ return recovered; } void lua_pack (void) { if (++gc_nentity >= gc_block) lua_collectgarbage(0); } /* ** Internal function: return next global variable */ void luaI_nextvar (void) { Word next = lua_isnil(lua_getparam(1)) ? 0 : luaI_findsymbolbyname(luaL_check_string(1))+1; if (next != 0) luaL_arg_check(s_ttype(next-1)!=LUA_T_NIL, 1, "undefined global name"); while (next < lua_ntable && s_ttype(next) == LUA_T_NIL) next++; if (next < lua_ntable) { lua_pushstring(lua_table[next].varname->str); luaI_pushobject(&s_object(next)); } } static TObject *functofind; static int checkfunc (TObject *o) { if (o->ttype == LUA_T_FUNCTION) return ((functofind->ttype == LUA_T_FUNCTION || functofind->ttype == LUA_T_MARK) && (functofind->value.tf == o->value.tf)); if (o->ttype == LUA_T_CFUNCTION) return ((functofind->ttype == LUA_T_CFUNCTION || functofind->ttype == LUA_T_CMARK) && (functofind->value.f == o->value.f)); return 0; } char *lua_getobjname (lua_Object o, char **name) { /* try to find a name for given function */ functofind = luaI_Address(o); if ((*name = luaI_travfallbacks(checkfunc)) != NULL) return "tag-method"; else if ((*name = lua_travsymbol(checkfunc)) != NULL) return "global"; else return ""; }