--- a/src/lapi.c +++ b/src/lapi.c @@ -27,8 +27,8 @@ #include "ltable.h" #include "ltm.h" #include "lundump.h" -#include "lvm.h" #include "lnum.h" +#include "lvm.h" const char lua_ident[] = @@ -117,6 +117,7 @@ LUA_API void lua_xmove (lua_State *from, from->top -= n; for (i = 0; i < n; i++) { setobj2s(to, to->top++, from->top + i); + setnilvalue(from, from->top + i); } lua_unlock(to); } @@ -166,12 +167,14 @@ LUA_API void lua_settop (lua_State *L, i if (idx >= 0) { api_check(L, idx <= L->stack_last - L->base); while (L->top < L->base + idx) - setnilvalue(L->top++); + setnilvalue(L, L->top++); L->top = L->base + idx; + setnilvalue(L, L->top); } else { + int i; api_check(L, -(idx+1) <= (L->top - L->base)); - L->top += idx+1; /* `subtract' index (index is negative) */ + setlvmtop(L, L->top + idx + 1); /* `subtract' index (index is negative) */ } lua_unlock(L); } @@ -183,7 +186,7 @@ LUA_API void lua_remove (lua_State *L, i p = index2adr(L, idx); api_checkvalidindex(L, p); while (++p < L->top) setobjs2s(L, p-1, p); - L->top--; + setlvmtop(L, L->top - 1); lua_unlock(L); } @@ -196,6 +199,7 @@ LUA_API void lua_insert (lua_State *L, i api_checkvalidindex(L, p); for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); setobjs2s(L, p, L->top); + setnilvalue(L, L->top); lua_unlock(L); } @@ -220,7 +224,7 @@ LUA_API void lua_replace (lua_State *L, if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ luaC_barrier(L, curr_func(L), L->top - 1); } - L->top--; + setlvmtop(L, L->top - 1); lua_unlock(L); } @@ -259,14 +263,14 @@ LUA_API int lua_iscfunction (lua_State * LUA_API int lua_isnumber (lua_State *L, int idx) { - TValue n; + TValue n = tvinit(); const TValue *o = index2adr(L, idx); return tonumber(o, &n); } LUA_API int lua_isinteger (lua_State *L, int idx) { - TValue tmp; + TValue tmp = tvinit(); lua_Integer dum; const TValue *o = index2adr(L, idx); return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum)); @@ -319,7 +323,7 @@ LUA_API int lua_lessthan (lua_State *L, LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { - TValue n; + TValue n = tvinit(); const TValue *o = index2adr(L, idx); if (tonumber(o, &n)) { #ifdef LNUM_COMPLEX @@ -333,7 +337,7 @@ LUA_API lua_Number lua_tonumber (lua_Sta LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { - TValue n; + TValue n = tvinit(); /* Lua 5.1 documented behaviour is to return nonzero for non-integer: * "If the number is not an integer, it is truncated in some non-specified way." * I would suggest to change this, to return 0 for anything that would @@ -369,7 +373,7 @@ LUA_API lua_Integer lua_tointeger (lua_S #ifdef LNUM_COMPLEX LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) { - TValue tmp; + TValue tmp = tvinit(); const TValue *o = index2adr(L, idx); if (tonumber(o, &tmp)) return nvalue_complex(o); @@ -465,7 +469,7 @@ LUA_API const void *lua_topointer (lua_S LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); - setnilvalue(L->top); + setnilvalue(L, L->top); api_incr_top(L); lua_unlock(L); } @@ -548,8 +552,10 @@ LUA_API void lua_pushcclosure (lua_State cl = luaF_newCclosure(L, n, getcurrenv(L)); cl->c.f = fn; L->top -= n; - while (n--) + while (n--) { setobj2n(L, &cl->c.upvalue[n], L->top+n); + setnilvalue(L, L->top + n); + } setclvalue(L, L->top, cl); lua_assert(iswhite(obj2gco(cl))); api_incr_top(L); @@ -600,7 +606,7 @@ LUA_API void lua_gettable (lua_State *L, LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { StkId t; - TValue key; + TValue key = tvinit(); lua_lock(L); t = index2adr(L, idx); api_checkvalidindex(L, t); @@ -689,7 +695,7 @@ LUA_API void lua_getfenv (lua_State *L, setobj2s(L, L->top, gt(thvalue(o))); break; default: - setnilvalue(L->top); + setnilvalue(L, L->top); break; } api_incr_top(L); @@ -709,21 +715,21 @@ LUA_API void lua_settable (lua_State *L, t = index2adr(L, idx); api_checkvalidindex(L, t); luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; /* pop index and value */ + setlvmtop(L, L->top - 2); /* pop index and value */ lua_unlock(L); } LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { StkId t; - TValue key; + TValue key = tvinit(); lua_lock(L); api_checknelems(L, 1); t = index2adr(L, idx); api_checkvalidindex(L, t); setsvalue(L, &key, luaS_new(L, k)); luaV_settable(L, t, &key, L->top - 1); - L->top--; /* pop value */ + setlvmtop(L, L->top - 1); /* pop value */ lua_unlock(L); } @@ -736,7 +742,7 @@ LUA_API void lua_rawset (lua_State *L, i api_check(L, ttistable(t)); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); luaC_barriert(L, hvalue(t), L->top-1); - L->top -= 2; + setlvmtop(L, L->top - 2); lua_unlock(L); } @@ -749,7 +755,7 @@ LUA_API void lua_rawseti (lua_State *L, api_check(L, ttistable(o)); setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); luaC_barriert(L, hvalue(o), L->top-1); - L->top--; + setlvmtop(L, L->top - 1); lua_unlock(L); } @@ -785,7 +791,7 @@ LUA_API int lua_setmetatable (lua_State break; } } - L->top--; + setlvmtop(L, L->top - 1); lua_unlock(L); return 1; } @@ -814,7 +820,7 @@ LUA_API int lua_setfenv (lua_State *L, i break; } if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); - L->top--; + setlvmtop(L, L->top - 1); lua_unlock(L); return res; } @@ -1040,8 +1046,9 @@ LUA_API int lua_next (lua_State *L, int if (more) { api_incr_top(L); } - else /* no more elements */ - L->top -= 1; /* remove key */ + else { /* no more elements */ + setlvmtop(L, L->top - 1); /* remove key */ + } lua_unlock(L); return more; } @@ -1053,7 +1060,7 @@ LUA_API void lua_concat (lua_State *L, i if (n >= 2) { luaC_checkGC(L); luaV_concat(L, n, cast_int(L->top - L->base) - 1); - L->top -= (n-1); + setlvmtop(L, L->top - (n-1)); } else if (n == 0) { /* push empty string */ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); @@ -1139,6 +1146,7 @@ LUA_API const char *lua_setupvalue (lua_ if (name) { L->top--; setobj(L, val, L->top); + setnilvalue(L, L->top); luaC_barrier(L, clvalue(fi), L->top); } lua_unlock(L); @@ -1160,7 +1168,7 @@ LUA_API const char *lua_setupvalue (lua_ int lua_pushvalue_as_number (lua_State *L, int idx) { const TValue *o = index2adr(L, idx); - TValue tmp; + TValue tmp = tvinit(); lua_Integer i; if (ttisnumber(o)) { if ( (!ttisint(o)) && tt_integer_valued(o,&i)) { --- a/src/lcode.c +++ b/src/lcode.c @@ -23,6 +23,7 @@ #include "lparser.h" #include "ltable.h" #include "lnum.h" +#include "lvm.h" #define hasjumps(e) ((e)->t != (e)->f) @@ -248,7 +249,7 @@ static int addk (FuncState *fs, TValue * setivalue(idx, fs->nk); luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, MAXARG_Bx, "constant table overflow"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + while (oldsize < f->sizek) setnilvalue(L, &f->k[oldsize++]); setobj(L, &f->k[fs->nk], v); luaC_barrier(L, f, v); return fs->nk++; @@ -257,21 +258,24 @@ static int addk (FuncState *fs, TValue * int luaK_stringK (FuncState *fs, TString *s) { - TValue o; + TValue o = tvinit(); setsvalue(fs->L, &o, s); + luaV_unref(fs->L, &o); return addk(fs, &o, &o); } int luaK_numberK (FuncState *fs, lua_Number r) { - TValue o; + lua_State *L = fs->L; + TValue o = tvinit(); setnvalue(&o, r); return addk(fs, &o, &o); } int luaK_integerK (FuncState *fs, lua_Integer r) { - TValue o; + lua_State *L = fs->L; + TValue o = tvinit(); setivalue(&o, r); return addk(fs, &o, &o); } @@ -279,22 +283,24 @@ int luaK_integerK (FuncState *fs, lua_In #ifdef LNUM_COMPLEX static int luaK_imagK (FuncState *fs, lua_Number r) { - TValue o; + lua_State *L = fs->L; + TValue o = tvinit(); setnvalue_complex(&o, r*I); return addk(fs, &o, &o); } #endif static int boolK (FuncState *fs, int b) { - TValue o; + lua_State *L = fs->L; + TValue o = tvinit(); setbvalue(&o, b); return addk(fs, &o, &o); } static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); + TValue k = tvinit(), v = tvinit(); + setnilvalue(fs->L, &v); /* cannot use nil as key; instead use table itself to represent nil */ sethvalue(fs->L, &k, fs->h); return addk(fs, &k, &v); --- a/src/ldebug.c +++ b/src/ldebug.c @@ -142,6 +142,7 @@ LUA_API const char *lua_setlocal (lua_St if (name) setobjs2s(L, ci->base + (n - 1), L->top - 1); L->top--; /* pop value */ + setnilvalue(L, L->top); lua_unlock(L); return name; } @@ -176,7 +177,7 @@ static void info_tailcall (lua_Debug *ar static void collectvalidlines (lua_State *L, Closure *f) { if (f == NULL || f->c.isC) { - setnilvalue(L->top); + setnilvalue(L, L->top); } else { Table *t = luaH_new(L, 0, 0); @@ -248,7 +249,7 @@ LUA_API int lua_getinfo (lua_State *L, c } status = auxgetinfo(L, what, ar, f, ci); if (strchr(what, 'f')) { - if (f == NULL) setnilvalue(L->top); + if (f == NULL) setnilvalue(L, L->top); else setclvalue(L, L->top, f); incr_top(L); } @@ -586,7 +587,7 @@ void luaG_concaterror (lua_State *L, Stk void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { - TValue temp; + TValue temp = tvinit(); if (luaV_tonumber(p1, &temp) == NULL) p2 = p1; /* first operand is wrong */ luaG_typeerror(L, p2, "perform arithmetic on"); --- a/src/ldo.c +++ b/src/ldo.c @@ -211,7 +211,7 @@ static StkId adjust_varargs (lua_State * Table *htab = NULL; StkId base, fixed; for (; actual < nfixargs; ++actual) - setnilvalue(L->top++); + setnilvalue(L, L->top++); #if defined(LUA_COMPAT_VARARG) if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ int nvar = actual - nfixargs; /* number of extra arguments */ @@ -229,7 +229,7 @@ static StkId adjust_varargs (lua_State * base = L->top; /* final position of first argument */ for (i=0; itop++, fixed+i); - setnilvalue(fixed+i); + setnilvalue(L, fixed+i); } /* add `arg' parameter */ if (htab) { @@ -294,7 +294,7 @@ int luaD_precall (lua_State *L, StkId fu ci->tailcalls = 0; ci->nresults = nresults; for (st = L->top; st < ci->top; st++) - setnilvalue(st); + setnilvalue(L, st); L->top = ci->top; if (L->hookmask & LUA_MASKCALL) { L->savedpc++; /* hooks assume 'pc' is already incremented */ @@ -354,8 +354,8 @@ int luaD_poscall (lua_State *L, StkId fi for (i = wanted; i != 0 && firstResult < L->top; i--) setobjs2s(L, res++, firstResult++); while (i-- > 0) - setnilvalue(res++); - L->top = res; + setnilvalue(L, res++); + setlvmtop(L, res); return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ } @@ -463,8 +463,12 @@ int luaD_pcall (lua_State *L, Pfunc func status = luaD_rawrunprotected(L, func, u); if (status != 0) { /* an error occurred? */ StkId oldtop = restorestack(L, old_top); + StkId curtop = L->top; + int i; luaF_close(L, oldtop); /* close eventual pending closures */ luaD_seterrorobj(L, status, oldtop); + for (i = (curtop - L->top); i-- > 0;) + setnilvalue(L, L->top + i); L->nCcalls = oldnCcalls; L->ci = restoreci(L, old_ci); L->base = L->ci->base; --- a/src/lfunc.c +++ b/src/lfunc.c @@ -17,7 +17,7 @@ #include "lmem.h" #include "lobject.h" #include "lstate.h" - +#include "lvm.h" Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { @@ -45,7 +45,7 @@ UpVal *luaF_newupval (lua_State *L) { UpVal *uv = luaM_new(L, UpVal); luaC_link(L, obj2gco(uv), LUA_TUPVAL); uv->v = &uv->u.value; - setnilvalue(uv->v); + setnilvalue(L, uv->v); return uv; } @@ -67,8 +67,14 @@ UpVal *luaF_findupval (lua_State *L, Stk uv = luaM_new(L, UpVal); /* not found: create a new one */ uv->tt = LUA_TUPVAL; uv->marked = luaC_white(g); - uv->v = level; /* current value lives in the stack */ + uv->v = luaV_ref(level); /* current value lives in the stack */ uv->next = *pp; /* chain it in the proper position */ + if (uv->next) { + uv->prev = uv->next->gch.prev; + uv->next->gch.prev = (GCObject *)uv; + } else { + uv->prev = NULL; + } *pp = obj2gco(uv); uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ uv->u.l.next = g->uvhead.u.l.next; --- a/src/lgc.c +++ b/src/lgc.c @@ -21,6 +21,7 @@ #include "lstring.h" #include "ltable.h" #include "ltm.h" +#include "lvm.h" #define GCSTEPSIZE 1024u @@ -265,7 +266,7 @@ static void traversestack (global_State for (o = l->stack; o < l->top; o++) markvalue(g, o); for (; o <= lim; o++) - setnilvalue(o); + setnilvalue(l, o); checkstacksizes(l, lim); } @@ -348,7 +349,7 @@ static int iscleared (const TValue *o, i /* ** clear collected entries from weaktables */ -static void cleartable (GCObject *l) { +static void cleartable (lua_State *L, GCObject *l) { while (l) { Table *h = gco2h(l); int i = h->sizearray; @@ -358,7 +359,7 @@ static void cleartable (GCObject *l) { while (i--) { TValue *o = &h->array[i]; if (iscleared(o, 0)) /* value was collected? */ - setnilvalue(o); /* remove value */ + setnilvalue(L, o); /* remove value */ } } i = sizenode(h); @@ -366,7 +367,7 @@ static void cleartable (GCObject *l) { Node *n = gnode(h, i); if (!ttisnil(gval(n)) && /* non-empty entry? */ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { - setnilvalue(gval(n)); /* remove value ... */ + setnilvalue(L, gval(n)); /* remove value ... */ removeentry(n); /* remove entry from table */ } } @@ -375,7 +376,7 @@ static void cleartable (GCObject *l) { } -static void freeobj (lua_State *L, GCObject *o) { +void luaC_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; @@ -418,10 +419,12 @@ static GCObject **sweeplist (lua_State * } else { /* must erase `curr' */ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); + if (curr->gch.next) + curr->gch.next->gch.prev = curr->gch.prev; *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); + luaC_freeobj(L, curr); } } return p; @@ -543,7 +546,7 @@ static void atomic (lua_State *L) { udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ marktmu(g); /* mark `preserved' userdata */ udsize += propagateall(g); /* remark, to propagate `preserveness' */ - cleartable(g->weak); /* remove collected objects from weak tables */ + cleartable(L, g->weak); /* remove collected objects from weak tables */ /* flip current white */ g->currentwhite = cast_byte(otherwhite(g)); g->sweepstrgc = 0; @@ -685,8 +688,11 @@ void luaC_barrierback (lua_State *L, Tab void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { global_State *g = G(L); + o->gch.prev = (GCObject*)&g->rootgc; o->gch.next = g->rootgc; g->rootgc = o; + if (o->gch.next) + o->gch.next->gch.prev = o; o->gch.marked = luaC_white(g); o->gch.tt = tt; } --- a/src/lgc.h +++ b/src/lgc.h @@ -105,6 +105,6 @@ LUAI_FUNC void luaC_link (lua_State *L, LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); - +LUAI_FUNC void luaC_freeobj (lua_State *L, GCObject *o); #endif --- a/src/lmem.c +++ b/src/lmem.c @@ -6,6 +6,7 @@ #include +#include #define lmem_c #define LUA_CORE @@ -80,6 +81,8 @@ void *luaM_realloc_ (lua_State *L, void if (block == NULL && nsize > 0) luaD_throw(L, LUA_ERRMEM); lua_assert((nsize == 0) == (block == NULL)); + if (nsize > osize) + memset((char *)block + osize, 0, nsize - osize); g->totalbytes = (g->totalbytes - osize) + nsize; return block; } --- a/src/lobject.h +++ b/src/lobject.h @@ -44,7 +44,7 @@ typedef union GCObject GCObject; ** Common Header for all collectable objects (in macro form, to be ** included in other objects) */ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked +#define CommonHeader GCObject *next; GCObject *prev; lu_byte tt; lu_byte marked /* @@ -83,6 +83,7 @@ typedef struct lua_TValue { TValuefields; } TValue; +#define tvinit() { .value.b = 0, .tt = 0 } /* Macros to test type */ #define ttisnil(o) (ttype(o) == LUA_TNIL) @@ -145,15 +146,15 @@ typedef struct lua_TValue { /* Macros to set values */ -#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) +#define setnilvalue(L, obj) (luaV_unref(L, (obj))->tt=LUA_TNIL) /* Must not have side effects, 'x' may be expression. */ #define setivalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; } + { TValue *i_o=luaV_unref(L, (obj)); i_o->value.i=(x); i_o->tt=LUA_TINT; } # define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } + { TValue *i_o=luaV_unref(L, (obj)); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } /* Note: Complex always has "inline", both are C99. */ @@ -170,45 +171,45 @@ typedef struct lua_TValue { #define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + { TValue *i_o=luaV_unref(L, (obj)); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } #define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + { TValue *i_o=luaV_unref(L, (obj)); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } #define setsvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ + { TValue *i_o=(obj); TString *val=(x); luaS_ref(val); luaV_unref(L, obj); \ + i_o->value.gc=cast(GCObject *, (val)); i_o->tt=LUA_TSTRING; \ checkliveness(G(L),i_o); } #define setuvalue(L,obj,x) \ - { TValue *i_o=(obj); \ + { TValue *i_o=luaV_unref(L, (obj)); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ checkliveness(G(L),i_o); } #define setthvalue(L,obj,x) \ - { TValue *i_o=(obj); \ + { TValue *i_o=luaV_unref(L, (obj)); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ checkliveness(G(L),i_o); } #define setclvalue(L,obj,x) \ - { TValue *i_o=(obj); \ + { TValue *i_o=luaV_unref(L, (obj)); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ checkliveness(G(L),i_o); } #define sethvalue(L,obj,x) \ - { TValue *i_o=(obj); \ + { TValue *i_o=luaV_unref(L, (obj)); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ checkliveness(G(L),i_o); } #define setptvalue(L,obj,x) \ - { TValue *i_o=(obj); \ + { TValue *i_o=luaV_unref(L, (obj)); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ checkliveness(G(L),i_o); } #define setobj(L,obj1,obj2) \ - { const TValue *o2=(obj2); TValue *o1=(obj1); \ + do { const TValue *o2=luaV_ref((TValue *)(obj2)); TValue *o1=luaV_unref(L, (obj1)); \ o1->value = o2->value; o1->tt=o2->tt; \ - checkliveness(G(L),o1); } + checkliveness(G(L),o1); } while(0) /* @@ -253,6 +254,7 @@ typedef union TString { lu_byte reserved; unsigned int hash; size_t len; + int refcount; } tsv; } TString; @@ -409,6 +411,7 @@ typedef struct Table { #define twoto(x) (1<<(x)) #define sizenode(t) (twoto((t)->lsizenode)) +#include "lstring.h" #define luaO_nilobject (&luaO_nilobject_) --- a/src/lparser.c +++ b/src/lparser.c @@ -24,6 +24,7 @@ #include "lstate.h" #include "lstring.h" #include "ltable.h" +#include "lvm.h" @@ -146,7 +147,7 @@ static int registerlocalvar (LexState *l luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, LocVar, SHRT_MAX, "too many local variables"); while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; + f->locvars[fs->nlocvars].varname = luaS_ref(varname); luaC_objbarrier(ls->L, f, varname); return fs->nlocvars++; } @@ -194,7 +195,7 @@ static int indexupvalue (FuncState *fs, luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, TString *, MAX_INT, ""); while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; - f->upvalues[f->nups] = name; + f->upvalues[f->nups] = luaS_ref(name); luaC_objbarrier(fs->L, f, name); lua_assert(v->k == VLOCAL || v->k == VUPVAL); fs->upvalues[f->nups].k = cast_byte(v->k); @@ -341,7 +342,7 @@ static void open_func (LexState *ls, Fun fs->nlocvars = 0; fs->nactvar = 0; fs->bl = NULL; - f->source = ls->source; + f->source = luaS_ref(ls->source); f->maxstacksize = 2; /* registers 0/1 are always valid */ fs->h = luaH_new(L, 0, 0); /* anchor table of constants and prototype (to avoid being collected) */ --- a/src/lstate.c +++ b/src/lstate.c @@ -22,6 +22,7 @@ #include "lstring.h" #include "ltable.h" #include "ltm.h" +#include "lvm.h" #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) @@ -52,7 +53,7 @@ static void stack_init (lua_State *L1, l L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; /* initialize first ci */ L1->ci->func = L1->top; - setnilvalue(L1->top++); /* `function' entry for this `ci' */ + setnilvalue(L1, L1->top++); /* `function' entry for this `ci' */ L1->base = L1->ci->base = L1->top; L1->ci->top = L1->top + LUA_MINSTACK; } @@ -98,7 +99,7 @@ static void preinit_state (lua_State *L, L->base_ci = L->ci = NULL; L->savedpc = NULL; L->errfunc = 0; - setnilvalue(gt(L)); + setnilvalue(L, gt(L)); } @@ -163,7 +164,7 @@ LUA_API lua_State *lua_newstate (lua_All g->strt.size = 0; g->strt.nuse = 0; g->strt.hash = NULL; - setnilvalue(registry(L)); + setnilvalue(L, registry(L)); luaZ_initbuffer(L, &g->buff); g->panic = NULL; g->gcstate = GCSpause; --- a/src/lstring.c +++ b/src/lstring.c @@ -37,6 +37,9 @@ void luaS_resize (lua_State *L, int news int h1 = lmod(h, newsize); /* new position */ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); p->gch.next = newhash[h1]; /* chain it */ + if (p->gch.next) + p->gch.next->gch.prev = p; + p->gch.prev = NULL; newhash[h1] = p; p = next; } @@ -59,11 +62,15 @@ static TString *newlstr (lua_State *L, c ts->tsv.marked = luaC_white(G(L)); ts->tsv.tt = LUA_TSTRING; ts->tsv.reserved = 0; + ts->tsv.refcount = 0; memcpy(ts+1, str, l*sizeof(char)); ((char *)(ts+1))[l] = '\0'; /* ending 0 */ tb = &G(L)->strt; h = lmod(h, tb->size); ts->tsv.next = tb->hash[h]; /* chain new entry */ + if (ts->tsv.next) + ts->tsv.next->gch.prev = (GCObject *)ts; + ts->tsv.prev = NULL; tb->hash[h] = obj2gco(ts); tb->nuse++; if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) @@ -109,3 +116,29 @@ Udata *luaS_newudata (lua_State *L, size return u; } +void luaS_unref(lua_State *L, TString *ts) { + if (!L || !ts) + return; + if (testbit(ts->tsv.marked, FIXEDBIT)) + return; + ts->tsv.refcount--; + if (ts->tsv.refcount < 0) { + fprintf(stderr, "REFCOUNT BUG, COUNT=%d, str=%s, len=%d\n", ts->tsv.refcount, (char *) (ts + 1), (int) ts->tsv.len); + } else if (ts->tsv.refcount) + return; + + if (ts->tsv.prev) { + ts->tsv.prev->gch.next = ts->tsv.next; + } else { + unsigned int idx = lmod(ts->tsv.hash, G(L)->strt.size); + lua_assert(G(L)->strt.hash[index] == (GCObject*)ts); + G(L)->strt.hash[idx] = ts->tsv.next; + } + + if (ts->tsv.next) + ts->tsv.next->gch.prev = ts->tsv.prev; + + luaC_freeobj(L, (GCObject *) ts); +} + + --- a/src/lstring.h +++ b/src/lstring.h @@ -7,7 +7,7 @@ #ifndef lstring_h #define lstring_h - +#include #include "lgc.h" #include "lobject.h" #include "lstate.h" @@ -23,6 +23,12 @@ #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) +static inline TString *luaS_ref(TString *ts) { + ts->tsv.refcount++; + return ts; +} + +LUA_API void luaS_unref(lua_State *L, TString *ts); LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l); --- a/src/ltable.c +++ b/src/ltable.c @@ -34,6 +34,7 @@ #include "lstate.h" #include "ltable.h" #include "lnum.h" +#include "lvm.h" /* @@ -278,7 +279,7 @@ static void setarrayvector (lua_State *L int i; luaM_reallocvector(L, t->array, t->sizearray, size, TValue); for (i=t->sizearray; iarray[i]); + setnilvalue(L, &t->array[i]); t->sizearray = size; } @@ -299,8 +300,8 @@ static void setnodevector (lua_State *L, for (i=0; ilsizenode = cast_byte(lsize); @@ -427,9 +428,11 @@ static TValue *newkey (lua_State *L, Tab othern = gnext(othern); /* find previous */ } gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + luaV_ref((TValue *) gkey(mp)); + luaV_ref(gval(mp)); *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ gnext(mp) = NULL; /* now `mp' is free */ - setnilvalue(gval(mp)); + setnilvalue(L, gval(mp)); } else { /* colliding node is in its own main position */ /* new node will go into free position */ @@ -438,6 +441,7 @@ static TValue *newkey (lua_State *L, Tab mp = n; } } + luaV_ref((TValue *) key); gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; luaC_barriert(L, t, key); lua_assert(ttisnil(gval(mp))); @@ -530,7 +534,7 @@ TValue *luaH_setint (lua_State *L, Table if (p != luaO_nilobject) return cast(TValue *, p); else { - TValue k; + TValue k = tvinit(); setivalue(&k, key); return newkey(L, t, &k); } @@ -542,7 +546,7 @@ TValue *luaH_setstr (lua_State *L, Table if (p != luaO_nilobject) return cast(TValue *, p); else { - TValue k; + TValue k = tvinit(); setsvalue(L, &k, key); return newkey(L, t, &k); } --- a/src/luac.c +++ b/src/luac.c @@ -20,8 +20,9 @@ #include "lmem.h" #include "lobject.h" #include "lopcodes.h" -#include "lstring.h" #include "lundump.h" +#include "lvm.h" +#include "lstring.h" #define PROGNAME "luac" /* default program name */ #define OUTPUT PROGNAME ".out" /* default output file */ --- a/src/lundump.c +++ b/src/lundump.c @@ -19,6 +19,7 @@ #include "lstring.h" #include "lundump.h" #include "lzio.h" +#include "lvm.h" typedef struct { lua_State* L; @@ -133,7 +134,7 @@ static TString* LoadString(LoadState* S) { char* s=luaZ_openspace(S->L,S->b,size); LoadBlock(S,s,size); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + return luaS_ref(luaS_newlstr(S->L,s,size-1)); /* remove trailing '\0' */ } } @@ -149,11 +150,12 @@ static Proto* LoadFunction(LoadState* S, static void LoadConstants(LoadState* S, Proto* f) { + lua_State *L = S->L; int i,n; n=LoadInt(S); f->k=luaM_newvector(S->L,n,TValue); f->sizek=n; - for (i=0; ik[i]); + for (i=0; ik[i]); for (i=0; ik[i]; @@ -161,7 +163,7 @@ static void LoadConstants(LoadState* S, switch (t) { case LUA_TNIL: - setnilvalue(o); + setnilvalue(L, o); break; case LUA_TBOOLEAN: setbvalue(o,LoadChar(S)!=0); @@ -229,6 +231,7 @@ static Proto* LoadFunction(LoadState* S, LoadDebug(S,f); IF (!luaG_checkcode(f), "bad code"); S->L->top--; + setnilvalue(S->L, S->L->top); S->L->nCcalls--; return f; } --- a/src/lvm.c +++ b/src/lvm.c @@ -39,6 +39,7 @@ * If 'obj' is a string, it is tried to be interpreted as a number. */ const TValue *luaV_tonumber ( const TValue *obj, TValue *n) { + lua_State *L = NULL; /* FIXME */ lua_Number d; lua_Integer i; @@ -384,6 +385,7 @@ void luaV_concat (lua_State *L, int tota size_t l = tsvalue(top-i)->len; memcpy(buffer+tl, svalue(top-i), l); tl += l; + setnilvalue(L, top - i); } setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); } @@ -420,7 +422,7 @@ void luaV_concat (lua_State *L, int tota */ static void Arith (lua_State *L, StkId ra, const TValue *rb, const TValue *rc, TMS op) { - TValue tempb, tempc; + TValue tempb = tvinit(), tempc = tvinit(); const TValue *b, *c; lua_Number nb,nc; @@ -663,7 +665,7 @@ void luaV_execute (lua_State *L, int nex OPCODE_TARGET(LOADNIL) { TValue *rb = RB(i); do { - setnilvalue(rb--); + setnilvalue(L, rb--); } while (rb >= ra); continue; } @@ -673,7 +675,7 @@ void luaV_execute (lua_State *L, int nex continue; } OPCODE_TARGET(GETGLOBAL) { - TValue g; + TValue g = tvinit(); TValue *rb = KBx(i); sethvalue(L, &g, cl->env); lua_assert(ttisstring(rb)); @@ -685,7 +687,7 @@ void luaV_execute (lua_State *L, int nex continue; } OPCODE_TARGET(SETGLOBAL) { - TValue g; + TValue g = tvinit(); sethvalue(L, &g, cl->env); lua_assert(ttisstring(KBx(i))); Protect(luaV_settable(L, &g, KBx(i), ra)); @@ -895,7 +897,7 @@ void luaV_execute (lua_State *L, int nex if (--nexeccalls == 0) /* was previous function running `here'? */ return; /* no: return */ else { /* yes: continue its execution */ - if (b) L->top = L->ci->top; + if (b) setlvmtop(L, L->ci->top); lua_assert(isLua(L->ci)); lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); goto reentry; @@ -986,6 +988,7 @@ void luaV_execute (lua_State *L, int nex for (; n > 0; n--) { TValue *val = ra+n; setobj2t(L, luaH_setint(L, h, last--), val); + setnilvalue(L, val); luaC_barriert(L, h, val); } continue; @@ -1030,7 +1033,7 @@ void luaV_execute (lua_State *L, int nex setobjs2s(L, ra + j, ci->base - n + j); } else { - setnilvalue(ra + j); + setnilvalue(L, ra + j); } } continue; --- a/src/lvm.h +++ b/src/lvm.h @@ -11,6 +11,7 @@ #include "ldo.h" #include "lobject.h" #include "ltm.h" +#include "lstring.h" #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) @@ -19,6 +20,19 @@ #define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2)) +static inline TValue *luaV_ref(TValue *tv) +{ + if (ttisstring(tv)) + luaS_ref(rawtsvalue(tv)); + return tv; +} + +static inline TValue *luaV_unref(lua_State *L, TValue *tv) +{ + if (ttisstring(tv)) + luaS_unref(L, rawtsvalue(tv)); + return tv; +} LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); --- a/src/llex.c +++ b/src/llex.c @@ -23,6 +23,7 @@ #include "ltable.h" #include "lzio.h" #include "lnum.h" +#include "lvm.h" @@ -69,7 +70,7 @@ static void save (LexState *ls, int c) { void luaX_init (lua_State *L) { int i; for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ @@ -125,7 +126,7 @@ void luaX_syntaxerror (LexState *ls, con TString *luaX_newstring (LexState *ls, const char *str, size_t l) { lua_State *L = ls->L; - TString *ts = luaS_newlstr(L, str, l); + TString *ts = luaS_ref(luaS_newlstr(L, str, l)); TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ if (ttisnil(o)) setbvalue(o, 1); /* make sure `str' will not be collected */ @@ -152,7 +153,7 @@ void luaX_setinput (lua_State *L, LexSta ls->fs = NULL; ls->linenumber = 1; ls->lastline = 1; - ls->source = source; + ls->source = luaS_ref(source); luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ next(ls); /* read first char */ } --- a/src/lstate.h +++ b/src/lstate.h @@ -144,6 +144,13 @@ union GCObject { struct lua_State th; /* thread */ }; +#define setlvmtop(L, val) do { \ + int __i; \ + for (__i = L->top - val; __i-- > 0;) \ + setnilvalue(L, val + __i); \ + L->top = val; \ +} while (0) + /* macros to convert a GCObject into a specific value */ #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))