summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/lua/SOURCES1
-rw-r--r--apps/plugins/lua/lapi.c22
-rw-r--r--apps/plugins/lua/lauxlib.c30
-rw-r--r--apps/plugins/lua/ldo.c21
-rw-r--r--apps/plugins/lua/lfunc.c2
-rw-r--r--apps/plugins/lua/lgc.c60
-rw-r--r--apps/plugins/lua/lgc.h24
-rw-r--r--apps/plugins/lua/lobject.h36
-rw-r--r--apps/plugins/lua/lparser.c6
-rw-r--r--apps/plugins/lua/lstate.c7
-rw-r--r--apps/plugins/lua/lstate.h1
-rw-r--r--apps/plugins/lua/lstring.c28
-rw-r--r--apps/plugins/lua/ltable.c3
-rw-r--r--apps/plugins/lua/lua_user.c18
-rw-r--r--apps/plugins/lua/lua_user.h14
-rw-r--r--apps/plugins/lua/luaconf.h6
-rw-r--r--apps/plugins/lua/lvm.c42
-rw-r--r--apps/plugins/lua/lzio.h2
-rw-r--r--apps/plugins/lua/rockconf.h1
-rw-r--r--apps/plugins/lua/rocklib.c6
-rw-r--r--apps/plugins/lua/tlsf_helper.c4
21 files changed, 266 insertions, 68 deletions
diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES
index 93fa5e9c83..481bf7672f 100644
--- a/apps/plugins/lua/SOURCES
+++ b/apps/plugins/lua/SOURCES
@@ -24,6 +24,7 @@ ltable.c
24ltablib.c 24ltablib.c
25ltm.c 25ltm.c
26lundump.c 26lundump.c
27lua_user.c
27lvm.c 28lvm.c
28lzio.c 29lzio.c
29rockaux.c 30rockaux.c
diff --git a/apps/plugins/lua/lapi.c b/apps/plugins/lua/lapi.c
index 487d6b173a..6426cd94a9 100644
--- a/apps/plugins/lua/lapi.c
+++ b/apps/plugins/lua/lapi.c
@@ -547,7 +547,9 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
547 lua_lock(L); 547 lua_lock(L);
548 t = index2adr(L, idx); 548 t = index2adr(L, idx);
549 api_checkvalidindex(L, t); 549 api_checkvalidindex(L, t);
550 fixedstack(L);
550 setsvalue(L, &key, luaS_new(L, k)); 551 setsvalue(L, &key, luaS_new(L, k));
552 unfixedstack(L);
551 luaV_gettable(L, t, &key, L->top); 553 luaV_gettable(L, t, &key, L->top);
552 api_incr_top(L); 554 api_incr_top(L);
553 lua_unlock(L); 555 lua_unlock(L);
@@ -656,14 +658,14 @@ LUA_API void lua_settable (lua_State *L, int idx) {
656 658
657LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { 659LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
658 StkId t; 660 StkId t;
659 TValue key;
660 lua_lock(L); 661 lua_lock(L);
661 api_checknelems(L, 1); 662 api_checknelems(L, 1);
662 t = index2adr(L, idx); 663 t = index2adr(L, idx);
663 api_checkvalidindex(L, t); 664 api_checkvalidindex(L, t);
664 setsvalue(L, &key, luaS_new(L, k)); 665 setsvalue2s(L, L->top, luaS_new(L, k));
665 luaV_settable(L, t, &key, L->top - 1); 666 api_incr_top(L);
666 L->top--; /* pop value */ 667 luaV_settable(L, t, L->top - 1, L->top - 2);
668 L->top -= 2; /* pop key and value */
667 lua_unlock(L); 669 lua_unlock(L);
668} 670}
669 671
@@ -674,7 +676,9 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
674 api_checknelems(L, 2); 676 api_checknelems(L, 2);
675 t = index2adr(L, idx); 677 t = index2adr(L, idx);
676 api_check(L, ttistable(t)); 678 api_check(L, ttistable(t));
679 fixedstack(L);
677 setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); 680 setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
681 unfixedstack(L);
678 luaC_barriert(L, hvalue(t), L->top-1); 682 luaC_barriert(L, hvalue(t), L->top-1);
679 L->top -= 2; 683 L->top -= 2;
680 lua_unlock(L); 684 lua_unlock(L);
@@ -687,7 +691,9 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
687 api_checknelems(L, 1); 691 api_checknelems(L, 1);
688 o = index2adr(L, idx); 692 o = index2adr(L, idx);
689 api_check(L, ttistable(o)); 693 api_check(L, ttistable(o));
694 fixedstack(L);
690 setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); 695 setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
696 unfixedstack(L);
691 luaC_barriert(L, hvalue(o), L->top-1); 697 luaC_barriert(L, hvalue(o), L->top-1);
692 L->top--; 698 L->top--;
693 lua_unlock(L); 699 lua_unlock(L);
@@ -903,11 +909,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
903 g = G(L); 909 g = G(L);
904 switch (what) { 910 switch (what) {
905 case LUA_GCSTOP: { 911 case LUA_GCSTOP: {
906 g->GCthreshold = MAX_LUMEM; 912 set_block_gc(L);
907 break; 913 break;
908 } 914 }
909 case LUA_GCRESTART: { 915 case LUA_GCRESTART: {
910 g->GCthreshold = g->totalbytes; 916 unset_block_gc(L);
911 break; 917 break;
912 } 918 }
913 case LUA_GCCOLLECT: { 919 case LUA_GCCOLLECT: {
@@ -924,6 +930,10 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
924 break; 930 break;
925 } 931 }
926 case LUA_GCSTEP: { 932 case LUA_GCSTEP: {
933 if(is_block_gc(L)) {
934 res = 1; /* gc is block so we need to pretend that the collection cycle finished. */
935 break;
936 }
927 lu_mem a = (cast(lu_mem, data) << 10); 937 lu_mem a = (cast(lu_mem, data) << 10);
928 if (a <= g->totalbytes) 938 if (a <= g->totalbytes)
929 g->GCthreshold = g->totalbytes - a; 939 g->GCthreshold = g->totalbytes - a;
diff --git a/apps/plugins/lua/lauxlib.c b/apps/plugins/lua/lauxlib.c
index 2e4b3b1e3c..acd7e0e636 100644
--- a/apps/plugins/lua/lauxlib.c
+++ b/apps/plugins/lua/lauxlib.c
@@ -13,7 +13,6 @@
13#include <string.h> 13#include <string.h>
14#include "lstring.h" /* ROCKLUA ADDED */ 14#include "lstring.h" /* ROCKLUA ADDED */
15 15
16
17/* This file uses only the official API of Lua. 16/* This file uses only the official API of Lua.
18** Any function declared here could be written as an application function. 17** Any function declared here could be written as an application function.
19** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED 18** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED
@@ -34,7 +33,9 @@
34#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ 33#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
35 lua_gettop(L) + (i) + 1) 34 lua_gettop(L) + (i) + 1)
36 35
37 36#ifndef LUA_OOM
37 #define LUA_OOM(L) {}
38#endif
38/* 39/*
39** {====================================================== 40** {======================================================
40** Error-report functions 41** Error-report functions
@@ -756,14 +757,30 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
756 757
757 758
758static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { 759static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
759 (void)ud; 760 (void) osize;
760 (void)osize; 761 lua_State *L = (lua_State *)ud;
762 void *nptr;
763
761 if (nsize == 0) { 764 if (nsize == 0) {
762 free(ptr); 765 free(ptr);
763 return NULL; 766 return NULL;
764 } 767 }
765 else 768
766 return realloc(ptr, nsize); 769 nptr = realloc(ptr, nsize);
770 if (nptr == NULL) {
771 if(L != NULL)
772 {
773 luaC_fullgc(L); /* emergency full collection. */
774 nptr = realloc(ptr, nsize); /* try allocation again */
775 }
776
777 if (nptr == NULL) {
778 LUA_OOM(L); /* if defined.. signal OOM condition */
779 nptr = realloc(ptr, nsize); /* try allocation again */
780 }
781 }
782
783 return nptr;
767} 784}
768 785
769 786
@@ -779,6 +796,7 @@ static int panic (lua_State *L) {
779 796
780LUALIB_API lua_State *luaL_newstate (void) { 797LUALIB_API lua_State *luaL_newstate (void) {
781 lua_State *L = lua_newstate(l_alloc, NULL); 798 lua_State *L = lua_newstate(l_alloc, NULL);
799 lua_setallocf(L, l_alloc, L); /* allocator needs lua_State. */
782 if (L) lua_atpanic(L, &panic); 800 if (L) lua_atpanic(L, &panic);
783 return L; 801 return L;
784} 802}
diff --git a/apps/plugins/lua/ldo.c b/apps/plugins/lua/ldo.c
index 43266de95e..7eccc54480 100644
--- a/apps/plugins/lua/ldo.c
+++ b/apps/plugins/lua/ldo.c
@@ -51,11 +51,13 @@ struct lua_longjmp {
51void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { 51void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
52 switch (errcode) { 52 switch (errcode) {
53 case LUA_ERRMEM: { 53 case LUA_ERRMEM: {
54 setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); 54 ptrdiff_t oldtopr = savestack(L, oldtop);
55 setsvalue2s(L, restorestack(L, oldtopr), luaS_newliteral(L, MEMERRMSG));
55 break; 56 break;
56 } 57 }
57 case LUA_ERRERR: { 58 case LUA_ERRERR: {
58 setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); 59 ptrdiff_t oldtopr = savestack(L, oldtop);
60 setsvalue2s(L, restorestack(L, oldtopr), luaS_newliteral(L, "error in error handling"));
59 break; 61 break;
60 } 62 }
61 case LUA_ERRSYNTAX: 63 case LUA_ERRSYNTAX:
@@ -92,6 +94,8 @@ static void resetstack (lua_State *L, int status) {
92 94
93 95
94void luaD_throw (lua_State *L, int errcode) { 96void luaD_throw (lua_State *L, int errcode) {
97 unfixedstack(L); /* make sure the fixedstack & block_gc flags get reset. */
98 unset_block_gc(L);
95 if (L->errorJmp) { 99 if (L->errorJmp) {
96 L->errorJmp->status = errcode; 100 L->errorJmp->status = errcode;
97 LUAI_THROW(L, L->errorJmp); 101 LUAI_THROW(L, L->errorJmp);
@@ -208,7 +212,9 @@ void luaD_callhook (lua_State *L, int event, int line) {
208static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { 212static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
209 int i; 213 int i;
210 int nfixargs = p->numparams; 214 int nfixargs = p->numparams;
215#if defined(LUA_COMPAT_VARARG)
211 Table *htab = NULL; 216 Table *htab = NULL;
217#endif
212 StkId base, fixed; 218 StkId base, fixed;
213 for (; actual < nfixargs; ++actual) 219 for (; actual < nfixargs; ++actual)
214 setnilvalue(L->top++); 220 setnilvalue(L->top++);
@@ -219,10 +225,15 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
219 luaC_checkGC(L); 225 luaC_checkGC(L);
220 luaD_checkstack(L, p->maxstacksize); 226 luaD_checkstack(L, p->maxstacksize);
221 htab = luaH_new(L, nvar, 1); /* create `arg' table */ 227 htab = luaH_new(L, nvar, 1); /* create `arg' table */
228 sethvalue2s(L, L->top, htab); /* put table on stack */
229 incr_top(L);
230 fixedstack(L);
222 for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ 231 for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
223 setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); 232 setobj2n(L, luaH_setnum(L, htab, i+1), L->top - 1 - nvar + i);
233 unfixedstack(L);
224 /* store counter in field `n' */ 234 /* store counter in field `n' */
225 setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); 235 setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
236 L->top--; /* remove table from stack */
226 } 237 }
227#endif 238#endif
228 /* move fixed parameters to final position */ 239 /* move fixed parameters to final position */
@@ -232,11 +243,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
232 setobjs2s(L, L->top++, fixed+i); 243 setobjs2s(L, L->top++, fixed+i);
233 setnilvalue(fixed+i); 244 setnilvalue(fixed+i);
234 } 245 }
246#if defined(LUA_COMPAT_VARARG)
235 /* add `arg' parameter */ 247 /* add `arg' parameter */
236 if (htab) { 248 if (htab) {
237 sethvalue(L, L->top++, htab); 249 sethvalue(L, L->top++, htab);
238 lua_assert(iswhite(obj2gco(htab))); 250 lua_assert(iswhite(obj2gco(htab)));
239 } 251 }
252#endif
240 return base; 253 return base;
241} 254}
242 255
@@ -495,6 +508,7 @@ static void f_parser (lua_State *L, void *ud) {
495 struct SParser *p = cast(struct SParser *, ud); 508 struct SParser *p = cast(struct SParser *, ud);
496 int c = luaZ_lookahead(p->z); 509 int c = luaZ_lookahead(p->z);
497 luaC_checkGC(L); 510 luaC_checkGC(L);
511 set_block_gc(L); /* stop collector during parsing */
498 tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, 512 tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
499 &p->buff, p->name); 513 &p->buff, p->name);
500 cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); 514 cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
@@ -503,6 +517,7 @@ static void f_parser (lua_State *L, void *ud) {
503 cl->l.upvals[i] = luaF_newupval(L); 517 cl->l.upvals[i] = luaF_newupval(L);
504 setclvalue(L, L->top, cl); 518 setclvalue(L, L->top, cl);
505 incr_top(L); 519 incr_top(L);
520 unset_block_gc(L);
506} 521}
507 522
508 523
diff --git a/apps/plugins/lua/lfunc.c b/apps/plugins/lua/lfunc.c
index 813e88f583..d2ce63dc4b 100644
--- a/apps/plugins/lua/lfunc.c
+++ b/apps/plugins/lua/lfunc.c
@@ -66,7 +66,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
66 } 66 }
67 uv = luaM_new(L, UpVal); /* not found: create a new one */ 67 uv = luaM_new(L, UpVal); /* not found: create a new one */
68 uv->tt = LUA_TUPVAL; 68 uv->tt = LUA_TUPVAL;
69 uv->marked = luaC_white(g);
70 uv->v = level; /* current value lives in the stack */ 69 uv->v = level; /* current value lives in the stack */
71 uv->next = *pp; /* chain it in the proper position */ 70 uv->next = *pp; /* chain it in the proper position */
72 *pp = obj2gco(uv); 71 *pp = obj2gco(uv);
@@ -74,6 +73,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
74 uv->u.l.next = g->uvhead.u.l.next; 73 uv->u.l.next = g->uvhead.u.l.next;
75 uv->u.l.next->u.l.prev = uv; 74 uv->u.l.next->u.l.prev = uv;
76 g->uvhead.u.l.next = uv; 75 g->uvhead.u.l.next = uv;
76 luaC_marknew(L, obj2gco(uv));
77 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); 77 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
78 return uv; 78 return uv;
79} 79}
diff --git a/apps/plugins/lua/lgc.c b/apps/plugins/lua/lgc.c
index 98194c1771..17b64a103b 100644
--- a/apps/plugins/lua/lgc.c
+++ b/apps/plugins/lua/lgc.c
@@ -58,6 +58,9 @@
58 58
59#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) 59#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
60 60
61#ifndef yield
62 #define yield() {}
63#endif
61 64
62static void removeentry (Node *n) { 65static void removeentry (Node *n) {
63 lua_assert(ttisnil(gval(n))); 66 lua_assert(ttisnil(gval(n)));
@@ -232,8 +235,10 @@ static void traverseclosure (global_State *g, Closure *cl) {
232 int i; 235 int i;
233 lua_assert(cl->l.nupvalues == cl->l.p->nups); 236 lua_assert(cl->l.nupvalues == cl->l.p->nups);
234 markobject(g, cl->l.p); 237 markobject(g, cl->l.p);
235 for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ 238 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
236 markobject(g, cl->l.upvals[i]); 239 if(cl->l.upvals[i])
240 markobject(g, cl->l.upvals[i]);
241 }
237 } 242 }
238} 243}
239 244
@@ -258,6 +263,7 @@ static void traversestack (global_State *g, lua_State *l) {
258 CallInfo *ci; 263 CallInfo *ci;
259 markvalue(g, gt(l)); 264 markvalue(g, gt(l));
260 lim = l->top; 265 lim = l->top;
266 if(l->stack == NULL) return; /* no stack to traverse */
261 for (ci = l->base_ci; ci <= l->ci; ci++) { 267 for (ci = l->base_ci; ci <= l->ci; ci++) {
262 lua_assert(ci->top <= l->stack_last); 268 lua_assert(ci->top <= l->stack_last);
263 if (lim < ci->top) lim = ci->top; 269 if (lim < ci->top) lim = ci->top;
@@ -266,7 +272,8 @@ static void traversestack (global_State *g, lua_State *l) {
266 markvalue(g, o); 272 markvalue(g, o);
267 for (; o <= lim; o++) 273 for (; o <= lim; o++)
268 setnilvalue(o); 274 setnilvalue(o);
269 checkstacksizes(l, lim); 275 if (!isfixedstack(l)) /* if stack size is fixed, can't resize it. */
276 checkstacksizes(l, lim);
270} 277}
271 278
272 279
@@ -419,8 +426,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
419 else { /* must erase `curr' */ 426 else { /* must erase `curr' */
420 lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); 427 lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
421 *p = curr->gch.next; 428 *p = curr->gch.next;
422 if (curr == g->rootgc) /* is the first element of the list? */
423 g->rootgc = curr->gch.next; /* adjust first */
424 freeobj(L, curr); 429 freeobj(L, curr);
425 } 430 }
426 } 431 }
@@ -434,6 +439,8 @@ static void checkSizes (lua_State *L) {
434 if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && 439 if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
435 g->strt.size > MINSTRTABSIZE*2) 440 g->strt.size > MINSTRTABSIZE*2)
436 luaS_resize(L, g->strt.size/2); /* table is too big */ 441 luaS_resize(L, g->strt.size/2); /* table is too big */
442 /* it is not safe to re-size the buffer if it is in use. */
443 if (luaZ_bufflen(&g->buff) > 0) return;
437 /* check size of buffer */ 444 /* check size of buffer */
438 if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ 445 if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
439 size_t newsize = luaZ_sizebuffer(&g->buff) / 2; 446 size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
@@ -552,6 +559,15 @@ static void atomic (lua_State *L) {
552 g->estimate = g->totalbytes - udsize; /* first estimate */ 559 g->estimate = g->totalbytes - udsize; /* first estimate */
553} 560}
554 561
562static void sweepstrstep (global_State *g, lua_State *L) {
563 lu_mem old = g->totalbytes;
564 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
565 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
566 g->gcstate = GCSsweep; /* end sweep-string phase */
567 lua_assert(old >= g->totalbytes);
568 g->estimate -= old - g->totalbytes;
569}
570
555 571
556static l_mem singlestep (lua_State *L) { 572static l_mem singlestep (lua_State *L) {
557 global_State *g = G(L); 573 global_State *g = G(L);
@@ -570,12 +586,7 @@ static l_mem singlestep (lua_State *L) {
570 } 586 }
571 } 587 }
572 case GCSsweepstring: { 588 case GCSsweepstring: {
573 lu_mem old = g->totalbytes; 589 sweepstrstep(g, L);
574 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
575 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
576 g->gcstate = GCSsweep; /* end sweep-string phase */
577 lua_assert(old >= g->totalbytes);
578 g->estimate -= old - g->totalbytes;
579 return GCSWEEPCOST; 590 return GCSWEEPCOST;
580 } 591 }
581 case GCSsweep: { 592 case GCSsweep: {
@@ -609,10 +620,14 @@ static l_mem singlestep (lua_State *L) {
609 620
610void luaC_step (lua_State *L) { 621void luaC_step (lua_State *L) {
611 global_State *g = G(L); 622 global_State *g = G(L);
623 if(is_block_gc(L)) return;
624 set_block_gc(L);
612 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; 625 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
613 if (lim == 0) 626 if (lim == 0)
614 lim = (MAX_LUMEM-1)/2; /* no limit */ 627 lim = (MAX_LUMEM-1)/2; /* no limit */
615 g->gcdept += g->totalbytes - g->GCthreshold; 628 g->gcdept += g->totalbytes - g->GCthreshold;
629 if (g->estimate > g->totalbytes)
630 g->estimate = g->totalbytes;
616 do { 631 do {
617 lim -= singlestep(L); 632 lim -= singlestep(L);
618 if (g->gcstate == GCSpause) 633 if (g->gcstate == GCSpause)
@@ -629,11 +644,23 @@ void luaC_step (lua_State *L) {
629 else { 644 else {
630 setthreshold(g); 645 setthreshold(g);
631 } 646 }
647 unset_block_gc(L);
632} 648}
633 649
634 650
651int luaC_sweepstrgc (lua_State *L) {
652 global_State *g = G(L);
653 if (g->gcstate == GCSsweepstring) {
654 sweepstrstep(g, L);
655 return (g->gcstate == GCSsweepstring) ? 1 : 0;
656 }
657 return 0;
658}
659
635void luaC_fullgc (lua_State *L) { 660void luaC_fullgc (lua_State *L) {
636 global_State *g = G(L); 661 global_State *g = G(L);
662 if(is_block_gc(L)) return;
663 set_block_gc(L);
637 if (g->gcstate <= GCSpropagate) { 664 if (g->gcstate <= GCSpropagate) {
638 /* reset sweep marks to sweep all elements (returning them to white) */ 665 /* reset sweep marks to sweep all elements (returning them to white) */
639 g->sweepstrgc = 0; 666 g->sweepstrgc = 0;
@@ -649,12 +676,15 @@ void luaC_fullgc (lua_State *L) {
649 while (g->gcstate != GCSfinalize) { 676 while (g->gcstate != GCSfinalize) {
650 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); 677 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
651 singlestep(L); 678 singlestep(L);
679 yield();
652 } 680 }
653 markroot(L); 681 markroot(L);
654 while (g->gcstate != GCSpause) { 682 while (g->gcstate != GCSpause) {
655 singlestep(L); 683 singlestep(L);
684 yield();
656 } 685 }
657 setthreshold(g); 686 setthreshold(g);
687 unset_block_gc(L);
658} 688}
659 689
660 690
@@ -682,6 +712,14 @@ void luaC_barrierback (lua_State *L, Table *t) {
682} 712}
683 713
684 714
715void luaC_marknew (lua_State *L, GCObject *o) {
716 global_State *g = G(L);
717 o->gch.marked = luaC_white(g);
718 if (g->gcstate == GCSpropagate)
719 reallymarkobject(g, o); /* mark new objects as gray during propagate state. */
720}
721
722
685void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { 723void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
686 global_State *g = G(L); 724 global_State *g = G(L);
687 o->gch.next = g->rootgc; 725 o->gch.next = g->rootgc;
diff --git a/apps/plugins/lua/lgc.h b/apps/plugins/lua/lgc.h
index 5123ccb479..115008d6be 100644
--- a/apps/plugins/lua/lgc.h
+++ b/apps/plugins/lua/lgc.h
@@ -37,12 +37,30 @@
37#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) 37#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
38 38
39 39
40/*
41** Possible Garbage Collector flags.
42** Layout for bit use in 'gsflags' field in global_State structure.
43** bit 0 - Protect GC from recursive calls.
44** bit 1 - Don't try to shrink string table if EGC was called during a string table resize.
45*/
46#define GCFlagsNone 0
47#define GCBlockGCBit 0
48#define GCResizingStringsBit 1
49
50
51#define is_block_gc(L) testbit(G(L)->gcflags, GCBlockGCBit)
52#define set_block_gc(L) l_setbit(G(L)->gcflags, GCBlockGCBit)
53#define unset_block_gc(L) resetbit(G(L)->gcflags, GCBlockGCBit)
54#define is_resizing_strings_gc(L) testbit(G(L)->gcflags, GCResizingStringsBit)
55#define set_resizing_strings_gc(L) l_setbit(G(L)->gcflags, GCResizingStringsBit)
56#define unset_resizing_strings_gc(L) resetbit(G(L)->gcflags, GCResizingStringsBit)
40 57
41/* 58/*
42** Layout for bit use in `marked' field: 59** Layout for bit use in `marked' field:
43** bit 0 - object is white (type 0) 60** bit 0 - object is white (type 0)
44** bit 1 - object is white (type 1) 61** bit 1 - object is white (type 1)
45** bit 2 - object is black 62** bit 2 - object is black
63** bit 3 - for thread: Don't resize thread's stack
46** bit 3 - for userdata: has been finalized 64** bit 3 - for userdata: has been finalized
47** bit 3 - for tables: has weak keys 65** bit 3 - for tables: has weak keys
48** bit 4 - for tables: has weak values 66** bit 4 - for tables: has weak values
@@ -54,6 +72,7 @@
54#define WHITE0BIT 0 72#define WHITE0BIT 0
55#define WHITE1BIT 1 73#define WHITE1BIT 1
56#define BLACKBIT 2 74#define BLACKBIT 2
75#define FIXEDSTACKBIT 3
57#define FINALIZEDBIT 3 76#define FINALIZEDBIT 3
58#define KEYWEAKBIT 3 77#define KEYWEAKBIT 3
59#define VALUEWEAKBIT 4 78#define VALUEWEAKBIT 4
@@ -76,6 +95,9 @@
76 95
77#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) 96#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
78 97
98#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
99#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
100#define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT)
79 101
80#define luaC_checkGC(L) { \ 102#define luaC_checkGC(L) { \
81 condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ 103 condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
@@ -101,6 +123,8 @@ LUAI_FUNC void luaC_callGCTM (lua_State *L);
101LUAI_FUNC void luaC_freeall (lua_State *L); 123LUAI_FUNC void luaC_freeall (lua_State *L);
102LUAI_FUNC void luaC_step (lua_State *L); 124LUAI_FUNC void luaC_step (lua_State *L);
103LUAI_FUNC void luaC_fullgc (lua_State *L); 125LUAI_FUNC void luaC_fullgc (lua_State *L);
126LUAI_FUNC int luaC_sweepstrgc (lua_State *L);
127LUAI_FUNC void luaC_marknew (lua_State *L, GCObject *o);
104LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); 128LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
105LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); 129LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
106LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); 130LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
diff --git a/apps/plugins/lua/lobject.h b/apps/plugins/lua/lobject.h
index 26d2a81b49..028ff0355b 100644
--- a/apps/plugins/lua/lobject.h
+++ b/apps/plugins/lua/lobject.h
@@ -117,42 +117,48 @@ typedef struct lua_TValue {
117#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) 117#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
118 118
119#define setnvalue(obj,x) \ 119#define setnvalue(obj,x) \
120 { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } 120 { lua_Number i_x = (x); TValue *i_o=(obj); i_o->value.n=i_x; i_o->tt=LUA_TNUMBER; }
121 121
122#define setpvalue(obj,x) \ 122#define setpvalue(obj,x) \
123 { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } 123 { void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTUSERDATA; }
124 124
125#define setbvalue(obj,x) \ 125#define setbvalue(obj,x) \
126 { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } 126 { int i_x = (x); TValue *i_o=(obj); i_o->value.b=i_x; i_o->tt=LUA_TBOOLEAN; }
127 127
128#define setsvalue(L,obj,x) \ 128#define setsvalue(L,obj,x) \
129 { TValue *i_o=(obj); \ 129 { GCObject *i_x = cast(GCObject *, (x)); \
130 i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ 130 TValue *i_o=(obj); \
131 i_o->value.gc=i_x; i_o->tt=LUA_TSTRING; \
131 checkliveness(G(L),i_o); } 132 checkliveness(G(L),i_o); }
132 133
133#define setuvalue(L,obj,x) \ 134#define setuvalue(L,obj,x) \
134 { TValue *i_o=(obj); \ 135 { GCObject *i_x = cast(GCObject *, (x)); \
135 i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ 136 TValue *i_o=(obj); \
137 i_o->value.gc=i_x; i_o->tt=LUA_TUSERDATA; \
136 checkliveness(G(L),i_o); } 138 checkliveness(G(L),i_o); }
137 139
138#define setthvalue(L,obj,x) \ 140#define setthvalue(L,obj,x) \
139 { TValue *i_o=(obj); \ 141 { GCObject *i_x = cast(GCObject *, (x)); \
140 i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ 142 TValue *i_o=(obj); \
143 i_o->value.gc=i_x; i_o->tt=LUA_TTHREAD; \
141 checkliveness(G(L),i_o); } 144 checkliveness(G(L),i_o); }
142 145
143#define setclvalue(L,obj,x) \ 146#define setclvalue(L,obj,x) \
144 { TValue *i_o=(obj); \ 147 { GCObject *i_x = cast(GCObject *, (x)); \
145 i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ 148 TValue *i_o=(obj); \
149 i_o->value.gc=i_x; i_o->tt=LUA_TFUNCTION; \
146 checkliveness(G(L),i_o); } 150 checkliveness(G(L),i_o); }
147 151
148#define sethvalue(L,obj,x) \ 152#define sethvalue(L,obj,x) \
149 { TValue *i_o=(obj); \ 153 { GCObject *i_x = cast(GCObject *, (x)); \
150 i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ 154 TValue *i_o=(obj); \
155 i_o->value.gc=i_x; i_o->tt=LUA_TTABLE; \
151 checkliveness(G(L),i_o); } 156 checkliveness(G(L),i_o); }
152 157
153#define setptvalue(L,obj,x) \ 158#define setptvalue(L,obj,x) \
154 { TValue *i_o=(obj); \ 159 { GCObject *i_x = cast(GCObject *, (x)); \
155 i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ 160 TValue *i_o=(obj); \
161 i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
156 checkliveness(G(L),i_o); } 162 checkliveness(G(L),i_o); }
157 163
158 164
diff --git a/apps/plugins/lua/lparser.c b/apps/plugins/lua/lparser.c
index dda7488dca..d002e96b86 100644
--- a/apps/plugins/lua/lparser.c
+++ b/apps/plugins/lua/lparser.c
@@ -383,14 +383,18 @@ static void close_func (LexState *ls) {
383Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { 383Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
384 struct LexState lexstate; 384 struct LexState lexstate;
385 struct FuncState funcstate; 385 struct FuncState funcstate;
386 TString *tname = luaS_new(L, name);
387 setsvalue2s(L, L->top, tname); /* protect name */
388 incr_top(L);
386 lexstate.buff = buff; 389 lexstate.buff = buff;
387 luaX_setinput(L, &lexstate, z, luaS_new(L, name)); 390 luaX_setinput(L, &lexstate, z, tname);
388 open_func(&lexstate, &funcstate); 391 open_func(&lexstate, &funcstate);
389 funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ 392 funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
390 luaX_next(&lexstate); /* read first token */ 393 luaX_next(&lexstate); /* read first token */
391 chunk(&lexstate); 394 chunk(&lexstate);
392 check(&lexstate, TK_EOS); 395 check(&lexstate, TK_EOS);
393 close_func(&lexstate); 396 close_func(&lexstate);
397 L->top--; /* remove 'name' from stack */
394 lua_assert(funcstate.prev == NULL); 398 lua_assert(funcstate.prev == NULL);
395 lua_assert(funcstate.f->nups == 0); 399 lua_assert(funcstate.f->nups == 0);
396 lua_assert(lexstate.fs == NULL); 400 lua_assert(lexstate.fs == NULL);
diff --git a/apps/plugins/lua/lstate.c b/apps/plugins/lua/lstate.c
index 4313b83a0c..67921d84a1 100644
--- a/apps/plugins/lua/lstate.c
+++ b/apps/plugins/lua/lstate.c
@@ -119,6 +119,8 @@ static void close_state (lua_State *L) {
119lua_State *luaE_newthread (lua_State *L) { 119lua_State *luaE_newthread (lua_State *L) {
120 lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); 120 lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
121 luaC_link(L, obj2gco(L1), LUA_TTHREAD); 121 luaC_link(L, obj2gco(L1), LUA_TTHREAD);
122 setthvalue(L, L->top, L1); /* put thread on stack */
123 incr_top(L);
122 preinit_state(L1, G(L)); 124 preinit_state(L1, G(L));
123 stack_init(L1, L); /* init stack */ 125 stack_init(L1, L); /* init stack */
124 setobj2n(L, gt(L1), gt(L)); /* share table of globals */ 126 setobj2n(L, gt(L1), gt(L)); /* share table of globals */
@@ -126,7 +128,8 @@ lua_State *luaE_newthread (lua_State *L) {
126 L1->basehookcount = L->basehookcount; 128 L1->basehookcount = L->basehookcount;
127 L1->hook = L->hook; 129 L1->hook = L->hook;
128 resethookcount(L1); 130 resethookcount(L1);
129 lua_assert(iswhite(obj2gco(L1))); 131 lua_assert(!isdead(G(L), obj2gco(L1)));
132 L->top--; /* remove thread from stack */
130 return L1; 133 return L1;
131} 134}
132 135
@@ -160,6 +163,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
160 g->uvhead.u.l.prev = &g->uvhead; 163 g->uvhead.u.l.prev = &g->uvhead;
161 g->uvhead.u.l.next = &g->uvhead; 164 g->uvhead.u.l.next = &g->uvhead;
162 g->GCthreshold = 0; /* mark it as unfinished state */ 165 g->GCthreshold = 0; /* mark it as unfinished state */
166 g->estimate = 0;
163 g->strt.size = 0; 167 g->strt.size = 0;
164 g->strt.nuse = 0; 168 g->strt.nuse = 0;
165 g->strt.hash = NULL; 169 g->strt.hash = NULL;
@@ -167,6 +171,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
167 luaZ_initbuffer(L, &g->buff); 171 luaZ_initbuffer(L, &g->buff);
168 g->panic = NULL; 172 g->panic = NULL;
169 g->gcstate = GCSpause; 173 g->gcstate = GCSpause;
174 g->gcflags = GCFlagsNone;
170 g->rootgc = obj2gco(L); 175 g->rootgc = obj2gco(L);
171 g->sweepstrgc = 0; 176 g->sweepstrgc = 0;
172 g->sweepgc = &g->rootgc; 177 g->sweepgc = &g->rootgc;
diff --git a/apps/plugins/lua/lstate.h b/apps/plugins/lua/lstate.h
index 94a6249461..82431bc5a9 100644
--- a/apps/plugins/lua/lstate.h
+++ b/apps/plugins/lua/lstate.h
@@ -71,6 +71,7 @@ typedef struct global_State {
71 void *ud; /* auxiliary data to `frealloc' */ 71 void *ud; /* auxiliary data to `frealloc' */
72 lu_byte currentwhite; 72 lu_byte currentwhite;
73 lu_byte gcstate; /* state of garbage collector */ 73 lu_byte gcstate; /* state of garbage collector */
74 lu_byte gcflags; /* flags for the garbage collector */
74 int sweepstrgc; /* position of sweep in `strt' */ 75 int sweepstrgc; /* position of sweep in `strt' */
75 GCObject *rootgc; /* list of all collectable objects */ 76 GCObject *rootgc; /* list of all collectable objects */
76 GCObject **sweepgc; /* position of sweep in `rootgc' */ 77 GCObject **sweepgc; /* position of sweep in `rootgc' */
diff --git a/apps/plugins/lua/lstring.c b/apps/plugins/lua/lstring.c
index bf0536e311..6d73f1e9ea 100644
--- a/apps/plugins/lua/lstring.c
+++ b/apps/plugins/lua/lstring.c
@@ -22,30 +22,34 @@
22 22
23 23
24void luaS_resize (lua_State *L, int newsize) { 24void luaS_resize (lua_State *L, int newsize) {
25 GCObject **newhash;
26 stringtable *tb; 25 stringtable *tb;
27 int i; 26 int i;
28 if (G(L)->gcstate == GCSsweepstring)
29 return; /* cannot resize during GC traverse */
30 newhash = luaM_newvector(L, newsize, GCObject *);
31 tb = &G(L)->strt; 27 tb = &G(L)->strt;
32 for (i=0; i<newsize; i++) newhash[i] = NULL; 28 if (luaC_sweepstrgc(L) || newsize == tb->size || is_resizing_strings_gc(L))
29 return; /* cannot resize during GC traverse or doesn't need to be resized */
30 set_resizing_strings_gc(L);
31 if (newsize > tb->size) {
32 luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
33 for (i=tb->size; i<newsize; i++) tb->hash[i] = NULL;
34 }
33 /* rehash */ 35 /* rehash */
34 for (i=0; i<tb->size; i++) { 36 for (i=0; i<tb->size; i++) {
35 GCObject *p = tb->hash[i]; 37 GCObject *p = tb->hash[i];
38 tb->hash[i] = NULL;
36 while (p) { /* for each node in the list */ 39 while (p) { /* for each node in the list */
37 GCObject *next = p->gch.next; /* save next */ 40 GCObject *next = p->gch.next; /* save next */
38 unsigned int h = gco2ts(p)->hash; 41 unsigned int h = gco2ts(p)->hash;
39 int h1 = lmod(h, newsize); /* new position */ 42 int h1 = lmod(h, newsize); /* new position */
40 lua_assert(cast_int(h%newsize) == lmod(h, newsize)); 43 lua_assert(cast_int(h%newsize) == lmod(h, newsize));
41 p->gch.next = newhash[h1]; /* chain it */ 44 p->gch.next = tb->hash[h1]; /* chain it */
42 newhash[h1] = p; 45 tb->hash[h1] = p;
43 p = next; 46 p = next;
44 } 47 }
45 } 48 }
46 luaM_freearray(L, tb->hash, tb->size, TString *); 49 if (newsize < tb->size)
50 luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
47 tb->size = newsize; 51 tb->size = newsize;
48 tb->hash = newhash; 52 unset_resizing_strings_gc(L);
49} 53}
50 54
51 55
@@ -55,6 +59,9 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
55 stringtable *tb; 59 stringtable *tb;
56 if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof("")) 60 if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof(""))
57 luaM_toobig(L); 61 luaM_toobig(L);
62 tb = &G(L)->strt;
63 if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
64 luaS_resize(L, tb->size*2); /* too crowded */
58 ts = cast(TString *, luaM_malloc(L, sizetstring(type, l))); 65 ts = cast(TString *, luaM_malloc(L, sizetstring(type, l)));
59 ts->tsv.len = l; 66 ts->tsv.len = l;
60 ts->tsv.hash = h; 67 ts->tsv.hash = h;
@@ -70,13 +77,10 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
70 memcpy(ts+1, str, l*sizeof(char)); 77 memcpy(ts+1, str, l*sizeof(char));
71 ((char *)(ts+1))[l] = '\0'; /* ending 0 */ 78 ((char *)(ts+1))[l] = '\0'; /* ending 0 */
72 } 79 }
73 tb = &G(L)->strt;
74 h = lmod(h, tb->size); 80 h = lmod(h, tb->size);
75 ts->tsv.next = tb->hash[h]; /* chain new entry */ 81 ts->tsv.next = tb->hash[h]; /* chain new entry */
76 tb->hash[h] = obj2gco(ts); 82 tb->hash[h] = obj2gco(ts);
77 tb->nuse++; 83 tb->nuse++;
78 if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
79 luaS_resize(L, tb->size*2); /* too crowded */
80 return ts; 84 return ts;
81} 85}
82 86
diff --git a/apps/plugins/lua/ltable.c b/apps/plugins/lua/ltable.c
index ec84f4fabc..31162fe7c1 100644
--- a/apps/plugins/lua/ltable.c
+++ b/apps/plugins/lua/ltable.c
@@ -358,6 +358,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
358Table *luaH_new (lua_State *L, int narray, int nhash) { 358Table *luaH_new (lua_State *L, int narray, int nhash) {
359 Table *t = luaM_new(L, Table); 359 Table *t = luaM_new(L, Table);
360 luaC_link(L, obj2gco(t), LUA_TTABLE); 360 luaC_link(L, obj2gco(t), LUA_TTABLE);
361 sethvalue2s(L, L->top, t); /* put table on stack */
362 incr_top(L);
361 t->metatable = NULL; 363 t->metatable = NULL;
362 t->flags = cast_byte(~0); 364 t->flags = cast_byte(~0);
363 /* temporary values (kept only if some malloc fails) */ 365 /* temporary values (kept only if some malloc fails) */
@@ -367,6 +369,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) {
367 t->node = cast(Node *, dummynode); 369 t->node = cast(Node *, dummynode);
368 setarrayvector(L, t, narray); 370 setarrayvector(L, t, narray);
369 setnodevector(L, t, nhash); 371 setnodevector(L, t, nhash);
372 L->top--; /* remove table from stack */
370 return t; 373 return t;
371} 374}
372 375
diff --git a/apps/plugins/lua/lua_user.c b/apps/plugins/lua/lua_user.c
new file mode 100644
index 0000000000..8d77dcdf3f
--- /dev/null
+++ b/apps/plugins/lua/lua_user.c
@@ -0,0 +1,18 @@
1#include "plugin.h"
2#include "lstate.h"
3#include LUA_USER_H
4
5/* lua Out Of Memory */
6static struct lua_OOM l_oom = {NULL, 0};
7
8int set_lua_OOM(lua_State * L)
9{
10 l_oom.L = L;
11 l_oom.count++;
12 return 0;
13}
14
15struct lua_OOM *get_lua_OOM(void)
16{
17 return &l_oom;
18}
diff --git a/apps/plugins/lua/lua_user.h b/apps/plugins/lua/lua_user.h
new file mode 100644
index 0000000000..f18f5e9d14
--- /dev/null
+++ b/apps/plugins/lua/lua_user.h
@@ -0,0 +1,14 @@
1#ifndef _LUA_USER_H_
2#define _LUA_USER_H_
3
4#define LUA_OOM(L) set_lua_OOM(L)
5
6struct lua_OOM {
7 lua_State * L;
8 int count;
9};
10
11int set_lua_OOM(lua_State * L);
12
13struct lua_OOM* get_lua_OOM(void);
14#endif
diff --git a/apps/plugins/lua/luaconf.h b/apps/plugins/lua/luaconf.h
index 582968d423..62a3ea0f6b 100644
--- a/apps/plugins/lua/luaconf.h
+++ b/apps/plugins/lua/luaconf.h
@@ -810,7 +810,13 @@ extern long rb_pow(long, long);
810/*Rocklua functions*/ 810/*Rocklua functions*/
811#include "rockconf.h" 811#include "rockconf.h"
812 812
813/* heap */
814#undef LUAI_GCPAUSE /*200*/
815#define LUAI_GCPAUSE 125
816#define MINSTRTABSIZE 512 /*32*/
817
813/*else*/ 818/*else*/
819#define LUA_USER_H "lua_user.h"
814#define LUA_DISABLE_BYTECODE 820#define LUA_DISABLE_BYTECODE
815 821
816#endif 822#endif
diff --git a/apps/plugins/lua/lvm.c b/apps/plugins/lua/lvm.c
index 35a931d7a1..4979b6a88e 100644
--- a/apps/plugins/lua/lvm.c
+++ b/apps/plugins/lua/lvm.c
@@ -49,9 +49,10 @@ int luaV_tostring (lua_State *L, StkId obj) {
49 return 0; 49 return 0;
50 else { 50 else {
51 char s[LUAI_MAXNUMBER2STR]; 51 char s[LUAI_MAXNUMBER2STR];
52 ptrdiff_t objr = savestack(L, obj);
52 lua_Number n = nvalue(obj); 53 lua_Number n = nvalue(obj);
53 lua_number2str(s, n); 54 lua_number2str(s, n);
54 setsvalue2s(L, obj, luaS_new(L, s)); 55 setsvalue2s(L, restorestack(L, objr), luaS_new(L, s));
55 return 1; 56 return 1;
56 } 57 }
57} 58}
@@ -134,6 +135,9 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
134void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { 135void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
135 int loop; 136 int loop;
136 TValue temp; 137 TValue temp;
138 setnilvalue(L->top);
139 L->top++;
140 fixedstack(L);
137 for (loop = 0; loop < MAXTAGLOOP; loop++) { 141 for (loop = 0; loop < MAXTAGLOOP; loop++) {
138 const TValue *tm; 142 const TValue *tm;
139 if (ttistable(t)) { /* `t' is a table? */ 143 if (ttistable(t)) { /* `t' is a table? */
@@ -141,6 +145,8 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
141 TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ 145 TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
142 if (!ttisnil(oldval) || /* result is no nil? */ 146 if (!ttisnil(oldval) || /* result is no nil? */
143 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ 147 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
148 L->top--;
149 unfixedstack(L);
144 setobj2t(L, oldval, val); 150 setobj2t(L, oldval, val);
145 h->flags = 0; 151 h->flags = 0;
146 luaC_barriert(L, h, val); 152 luaC_barriert(L, h, val);
@@ -151,12 +157,15 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
151 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) 157 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
152 luaG_typeerror(L, t, "index"); 158 luaG_typeerror(L, t, "index");
153 if (ttisfunction(tm)) { 159 if (ttisfunction(tm)) {
160 L->top--;
161 unfixedstack(L);
154 callTM(L, tm, t, key, val); 162 callTM(L, tm, t, key, val);
155 return; 163 return;
156 } 164 }
157 /* else repeat with `tm' */ 165 /* else repeat with `tm' */
158 setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ 166 setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */
159 t = &temp; 167 t = &temp;
168 setobj2s(L, L->top-1, t); /* need to protect value from EGC. */
160 } 169 }
161 luaG_runerror(L, "loop in settable"); 170 luaG_runerror(L, "loop in settable");
162} 171}
@@ -284,8 +293,11 @@ void luaV_concat (lua_State *L, int total, int last) {
284 StkId top = L->base + last + 1; 293 StkId top = L->base + last + 1;
285 int n = 2; /* number of elements handled in this pass (at least 2) */ 294 int n = 2; /* number of elements handled in this pass (at least 2) */
286 if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { 295 if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
287 if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) 296 if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) {
297 /* restore 'top' pointer, since stack might have been reallocted */
298 top = L->base + last + 1;
288 luaG_concaterror(L, top-2, top-1); 299 luaG_concaterror(L, top-2, top-1);
300 }
289 } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ 301 } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
290 (void)tostring(L, top - 2); /* result is first op (as string) */ 302 (void)tostring(L, top - 2); /* result is first op (as string) */
291 else { 303 else {
@@ -293,12 +305,14 @@ void luaV_concat (lua_State *L, int total, int last) {
293 size_t tl = tsvalue(top-1)->len; 305 size_t tl = tsvalue(top-1)->len;
294 char *buffer; 306 char *buffer;
295 int i; 307 int i;
308 fixedstack(L);
296 /* collect total length */ 309 /* collect total length */
297 for (n = 1; n < total && tostring(L, top-n-1); n++) { 310 for (n = 1; n < total && tostring(L, top-n-1); n++) {
298 size_t l = tsvalue(top-n-1)->len; 311 size_t l = tsvalue(top-n-1)->len;
299 if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); 312 if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
300 tl += l; 313 tl += l;
301 } 314 }
315 G(L)->buff.n = tl;
302 buffer = luaZ_openspace(L, &G(L)->buff, tl); 316 buffer = luaZ_openspace(L, &G(L)->buff, tl);
303 tl = 0; 317 tl = 0;
304 for (i=n; i>0; i--) { /* concat all strings */ 318 for (i=n; i>0; i--) { /* concat all strings */
@@ -307,6 +321,8 @@ void luaV_concat (lua_State *L, int total, int last) {
307 tl += l; 321 tl += l;
308 } 322 }
309 setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); 323 setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
324 luaZ_resetbuffer(&G(L)->buff);
325 unfixedstack(L);
310 } 326 }
311 total -= n-1; /* got `n' strings to create 1 new */ 327 total -= n-1; /* got `n' strings to create 1 new */
312 last -= n-1; 328 last -= n-1;
@@ -332,8 +348,13 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
332 default: lua_assert(0); break; 348 default: lua_assert(0); break;
333 } 349 }
334 } 350 }
335 else if (!call_binTM(L, rb, rc, ra, op)) 351 else {
336 luaG_aritherror(L, rb, rc); 352 ptrdiff_t br = savestack(L, rb);
353 ptrdiff_t cr = savestack(L, rc);
354 if (!call_binTM(L, rb, rc, ra, op)) {
355 luaG_aritherror(L, restorestack(L, br), restorestack(L, cr));
356 }
357 }
337} 358}
338 359
339 360
@@ -461,7 +482,9 @@ void luaV_execute (lua_State *L, int nexeccalls) {
461 case OP_NEWTABLE: { 482 case OP_NEWTABLE: {
462 int b = GETARG_B(i); 483 int b = GETARG_B(i);
463 int c = GETARG_C(i); 484 int c = GETARG_C(i);
464 sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); 485 Table *h;
486 Protect(h = luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
487 sethvalue(L, RA(i), h);
465 Protect(luaC_checkGC(L)); 488 Protect(luaC_checkGC(L));
466 continue; 489 continue;
467 } 490 }
@@ -547,9 +570,10 @@ void luaV_execute (lua_State *L, int nexeccalls) {
547 break; 570 break;
548 } 571 }
549 default: { /* try metamethod */ 572 default: { /* try metamethod */
573 ptrdiff_t br = savestack(L, rb);
550 Protect( 574 Protect(
551 if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) 575 if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
552 luaG_typeerror(L, rb, "get length of"); 576 luaG_typeerror(L, restorestack(L, br), "get length of");
553 ) 577 )
554 } 578 }
555 } 579 }
@@ -723,6 +747,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
723 int c = GETARG_C(i); 747 int c = GETARG_C(i);
724 int last; 748 int last;
725 Table *h; 749 Table *h;
750 fixedstack(L);
726 if (n == 0) { 751 if (n == 0) {
727 n = cast_int(L->top - ra) - 1; 752 n = cast_int(L->top - ra) - 1;
728 L->top = L->ci->top; 753 L->top = L->ci->top;
@@ -738,6 +763,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
738 setobj2t(L, luaH_setnum(L, h, last--), val); 763 setobj2t(L, luaH_setnum(L, h, last--), val);
739 luaC_barriert(L, h, val); 764 luaC_barriert(L, h, val);
740 } 765 }
766 unfixedstack(L);
741 continue; 767 continue;
742 } 768 }
743 case OP_CLOSE: { 769 case OP_CLOSE: {
@@ -750,7 +776,9 @@ void luaV_execute (lua_State *L, int nexeccalls) {
750 int nup, j; 776 int nup, j;
751 p = cl->p->p[GETARG_Bx(i)]; 777 p = cl->p->p[GETARG_Bx(i)];
752 nup = p->nups; 778 nup = p->nups;
779 fixedstack(L);
753 ncl = luaF_newLclosure(L, nup, cl->env); 780 ncl = luaF_newLclosure(L, nup, cl->env);
781 setclvalue(L, ra, ncl);
754 ncl->l.p = p; 782 ncl->l.p = p;
755 for (j=0; j<nup; j++, pc++) { 783 for (j=0; j<nup; j++, pc++) {
756 if (GET_OPCODE(*pc) == OP_GETUPVAL) 784 if (GET_OPCODE(*pc) == OP_GETUPVAL)
@@ -760,7 +788,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
760 ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); 788 ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
761 } 789 }
762 } 790 }
763 setclvalue(L, ra, ncl); 791 unfixedstack(L);
764 Protect(luaC_checkGC(L)); 792 Protect(luaC_checkGC(L));
765 continue; 793 continue;
766 } 794 }
diff --git a/apps/plugins/lua/lzio.h b/apps/plugins/lua/lzio.h
index 9aa9e4b537..cb32e6abc4 100644
--- a/apps/plugins/lua/lzio.h
+++ b/apps/plugins/lua/lzio.h
@@ -27,7 +27,7 @@ typedef struct Mbuffer {
27 size_t buffsize; 27 size_t buffsize;
28} Mbuffer; 28} Mbuffer;
29 29
30#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) 30#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->n = 0, (buff)->buffsize = 0)
31 31
32#define luaZ_buffer(buff) ((buff)->buffer) 32#define luaZ_buffer(buff) ((buff)->buffer)
33#define luaZ_sizebuffer(buff) ((buff)->buffsize) 33#define luaZ_sizebuffer(buff) ((buff)->buffsize)
diff --git a/apps/plugins/lua/rockconf.h b/apps/plugins/lua/rockconf.h
index 89ab82e377..6a1141f86a 100644
--- a/apps/plugins/lua/rockconf.h
+++ b/apps/plugins/lua/rockconf.h
@@ -63,6 +63,7 @@ long lpow(long x, long y);
63#define strcmp rb->strcmp 63#define strcmp rb->strcmp
64#define strcpy rb->strcpy 64#define strcpy rb->strcpy
65#define strlen rb->strlen 65#define strlen rb->strlen
66#define yield() rb->yield()
66 67
67#endif /* _ROCKCONF_H_ */ 68#endif /* _ROCKCONF_H_ */
68 69
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c
index d1ef3adaaf..c266516602 100644
--- a/apps/plugins/lua/rocklib.c
+++ b/apps/plugins/lua/rocklib.c
@@ -304,7 +304,7 @@ RB_WRAP(playlist)
304 break; 304 break;
305 } 305 }
306 306
307 rb->yield(); 307 yield();
308 lua_pushinteger(L, result); 308 lua_pushinteger(L, result);
309 return 1; 309 return 1;
310} 310}
@@ -382,7 +382,7 @@ RB_WRAP(audio)
382 return 1; 382 return 1;
383 } 383 }
384 384
385 rb->yield(); 385 yield();
386 lua_pushinteger(L, status); /* return previous (or current) audio status */ 386 lua_pushinteger(L, status); /* return previous (or current) audio status */
387 return 1; 387 return 1;
388} 388}
@@ -502,7 +502,7 @@ RB_WRAP(pcm)
502 break; 502 break;
503 } 503 }
504 504
505 rb->yield(); 505 yield();
506 return 1; 506 return 1;
507} 507}
508 508
diff --git a/apps/plugins/lua/tlsf_helper.c b/apps/plugins/lua/tlsf_helper.c
index edf32eecf9..097d39c8e4 100644
--- a/apps/plugins/lua/tlsf_helper.c
+++ b/apps/plugins/lua/tlsf_helper.c
@@ -20,6 +20,7 @@
20 20
21#include "plugin.h" 21#include "plugin.h"
22#include <tlsf.h> 22#include <tlsf.h>
23#include "lua.h"
23 24
24void *get_new_area(size_t *size) 25void *get_new_area(size_t *size)
25{ 26{
@@ -36,7 +37,8 @@ void *get_new_area(size_t *size)
36 return pluginbuf_ptr; 37 return pluginbuf_ptr;
37 } 38 }
38 39
39 if (audiobuf_ptr == NULL) 40 /* only grab the next area if lua already tried + failed to garbage collect*/
41 if (audiobuf_ptr == NULL && (get_lua_OOM())->count > 0)
40 { 42 {
41 /* grab audiobuffer */ 43 /* grab audiobuffer */
42 audiobuf_ptr = rb->plugin_get_audio_buffer(size); 44 audiobuf_ptr = rb->plugin_get_audio_buffer(size);