diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2010-03-30 23:24:46 +0000 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2010-03-30 23:24:46 +0000 |
commit | fe6b17f6ad14f03a6b7530b0125c6fb05735aee3 (patch) | |
tree | 2fef86c77249fc73f3caa932c3121ccf305b8f1d | |
parent | 1c25cfcde00f469cd022c60affc7162bd5bfef06 (diff) | |
download | upstream-fe6b17f6ad14f03a6b7530b0125c6fb05735aee3.tar.gz upstream-fe6b17f6ad14f03a6b7530b0125c6fb05735aee3.tar.bz2 upstream-fe6b17f6ad14f03a6b7530b0125c6fb05735aee3.zip |
lua: drop refcounting patch in preparation for 10.03, it has unresolved issues resulting in random vm crashes
SVN-Revision: 20617
-rw-r--r-- | package/lua/Makefile | 2 | ||||
-rw-r--r-- | package/lua/patches/600-refcounting.patch | 1128 |
2 files changed, 1 insertions, 1129 deletions
diff --git a/package/lua/Makefile b/package/lua/Makefile index c8c64badf4..0a5e8f3435 100644 --- a/package/lua/Makefile +++ b/package/lua/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lua PKG_VERSION:=5.1.4 -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.lua.org/ftp/ \ diff --git a/package/lua/patches/600-refcounting.patch b/package/lua/patches/600-refcounting.patch deleted file mode 100644 index 554a7c42e9..0000000000 --- a/package/lua/patches/600-refcounting.patch +++ /dev/null @@ -1,1128 +0,0 @@ ---- 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; i<nfixargs; i++) { - setobjs2s(L, L->top++, 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 <stddef.h> -+#include <string.h> - - #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 <stdio.h> - #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; i<size; i++) -- setnilvalue(&t->array[i]); -+ setnilvalue(L, &t->array[i]); - t->sizearray = size; - } - -@@ -299,8 +300,8 @@ static void setnodevector (lua_State *L, - for (i=0; i<size; i++) { - Node *n = gnode(t, i); - gnext(n) = NULL; -- setnilvalue(gkey(n)); -- setnilvalue(gval(n)); -+ setnilvalue(L, gkey(n)); -+ setnilvalue(L, gval(n)); - } - } - t->lsizenode = 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; i<n; i++) setnilvalue(&f->k[i]); -+ for (i=0; i<n; i++) setnilvalue(L, &f->k[i]); - for (i=0; i<n; i++) - { - TValue* o=&f->k[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; i<NUM_RESERVED; i++) { -- TString *ts = luaS_new(L, luaX_tokens[i]); -+ TString *ts = luaS_ref(luaS_new(L, luaX_tokens[i])); - luaS_fix(ts); /* reserved words are never collected */ - lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN); - ts->tsv.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)) |