lua: drop refcounting patch in preparation for 10.03, it has unresolved issues result...
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 30 Mar 2010 23:24:46 +0000 (23:24 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Tue, 30 Mar 2010 23:24:46 +0000 (23:24 +0000)
SVN-Revision: 20617

package/lua/Makefile
package/lua/patches/600-refcounting.patch [deleted file]

index c8c64badf47aa59c5569ca1cb8e992c5e8717d8a..0a5e8f34351d10bb0b45507023811da2ae4e7130 100644 (file)
@@ -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 (file)
index 554a7c4..0000000
+++ /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))