diff options
-rw-r--r-- | apps/plugins/lua/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/lua/lapi.c | 22 | ||||
-rw-r--r-- | apps/plugins/lua/lauxlib.c | 30 | ||||
-rw-r--r-- | apps/plugins/lua/ldo.c | 21 | ||||
-rw-r--r-- | apps/plugins/lua/lfunc.c | 2 | ||||
-rw-r--r-- | apps/plugins/lua/lgc.c | 60 | ||||
-rw-r--r-- | apps/plugins/lua/lgc.h | 24 | ||||
-rw-r--r-- | apps/plugins/lua/lobject.h | 36 | ||||
-rw-r--r-- | apps/plugins/lua/lparser.c | 6 | ||||
-rw-r--r-- | apps/plugins/lua/lstate.c | 7 | ||||
-rw-r--r-- | apps/plugins/lua/lstate.h | 1 | ||||
-rw-r--r-- | apps/plugins/lua/lstring.c | 28 | ||||
-rw-r--r-- | apps/plugins/lua/ltable.c | 3 | ||||
-rw-r--r-- | apps/plugins/lua/lua_user.c | 18 | ||||
-rw-r--r-- | apps/plugins/lua/lua_user.h | 14 | ||||
-rw-r--r-- | apps/plugins/lua/luaconf.h | 6 | ||||
-rw-r--r-- | apps/plugins/lua/lvm.c | 42 | ||||
-rw-r--r-- | apps/plugins/lua/lzio.h | 2 | ||||
-rw-r--r-- | apps/plugins/lua/rockconf.h | 1 | ||||
-rw-r--r-- | apps/plugins/lua/rocklib.c | 6 | ||||
-rw-r--r-- | apps/plugins/lua/tlsf_helper.c | 4 |
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 ltablib.c ltm.c lundump.c +lua_user.c lvm.c lzio.c rockaux.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) { lua_lock(L); t = index2adr(L, idx); api_checkvalidindex(L, t); + fixedstack(L); setsvalue(L, &key, luaS_new(L, k)); + unfixedstack(L); luaV_gettable(L, t, &key, L->top); api_incr_top(L); lua_unlock(L); @@ -656,14 +658,14 @@ LUA_API void lua_settable (lua_State *L, int idx) { LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { StkId t; - TValue key; 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 */ + setsvalue2s(L, L->top, luaS_new(L, k)); + api_incr_top(L); + luaV_settable(L, t, L->top - 1, L->top - 2); + L->top -= 2; /* pop key and value */ lua_unlock(L); } @@ -674,7 +676,9 @@ LUA_API void lua_rawset (lua_State *L, int idx) { api_checknelems(L, 2); t = index2adr(L, idx); api_check(L, ttistable(t)); + fixedstack(L); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + unfixedstack(L); luaC_barriert(L, hvalue(t), L->top-1); L->top -= 2; lua_unlock(L); @@ -687,7 +691,9 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) { api_checknelems(L, 1); o = index2adr(L, idx); api_check(L, ttistable(o)); + fixedstack(L); setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); + unfixedstack(L); luaC_barriert(L, hvalue(o), L->top-1); L->top--; lua_unlock(L); @@ -903,11 +909,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { g = G(L); switch (what) { case LUA_GCSTOP: { - g->GCthreshold = MAX_LUMEM; + set_block_gc(L); break; } case LUA_GCRESTART: { - g->GCthreshold = g->totalbytes; + unset_block_gc(L); break; } case LUA_GCCOLLECT: { @@ -924,6 +930,10 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { break; } case LUA_GCSTEP: { + if(is_block_gc(L)) { + res = 1; /* gc is block so we need to pretend that the collection cycle finished. */ + break; + } lu_mem a = (cast(lu_mem, data) << 10); if (a <= g->totalbytes) 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 @@ #include <string.h> #include "lstring.h" /* ROCKLUA ADDED */ - /* This file uses only the official API of Lua. ** Any function declared here could be written as an application function. ** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED @@ -34,7 +33,9 @@ #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ lua_gettop(L) + (i) + 1) - +#ifndef LUA_OOM + #define LUA_OOM(L) {} +#endif /* ** {====================================================== ** Error-report functions @@ -756,14 +757,30 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; - (void)osize; + (void) osize; + lua_State *L = (lua_State *)ud; + void *nptr; + if (nsize == 0) { free(ptr); return NULL; } - else - return realloc(ptr, nsize); + + nptr = realloc(ptr, nsize); + if (nptr == NULL) { + if(L != NULL) + { + luaC_fullgc(L); /* emergency full collection. */ + nptr = realloc(ptr, nsize); /* try allocation again */ + } + + if (nptr == NULL) { + LUA_OOM(L); /* if defined.. signal OOM condition */ + nptr = realloc(ptr, nsize); /* try allocation again */ + } + } + + return nptr; } @@ -779,6 +796,7 @@ static int panic (lua_State *L) { LUALIB_API lua_State *luaL_newstate (void) { lua_State *L = lua_newstate(l_alloc, NULL); + lua_setallocf(L, l_alloc, L); /* allocator needs lua_State. */ if (L) lua_atpanic(L, &panic); return L; } 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 { void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { switch (errcode) { case LUA_ERRMEM: { - setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); + ptrdiff_t oldtopr = savestack(L, oldtop); + setsvalue2s(L, restorestack(L, oldtopr), luaS_newliteral(L, MEMERRMSG)); break; } case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + ptrdiff_t oldtopr = savestack(L, oldtop); + setsvalue2s(L, restorestack(L, oldtopr), luaS_newliteral(L, "error in error handling")); break; } case LUA_ERRSYNTAX: @@ -92,6 +94,8 @@ static void resetstack (lua_State *L, int status) { void luaD_throw (lua_State *L, int errcode) { + unfixedstack(L); /* make sure the fixedstack & block_gc flags get reset. */ + unset_block_gc(L); if (L->errorJmp) { L->errorJmp->status = errcode; LUAI_THROW(L, L->errorJmp); @@ -208,7 +212,9 @@ void luaD_callhook (lua_State *L, int event, int line) { static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { int i; int nfixargs = p->numparams; +#if defined(LUA_COMPAT_VARARG) Table *htab = NULL; +#endif StkId base, fixed; for (; actual < nfixargs; ++actual) setnilvalue(L->top++); @@ -219,10 +225,15 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { luaC_checkGC(L); luaD_checkstack(L, p->maxstacksize); htab = luaH_new(L, nvar, 1); /* create `arg' table */ + sethvalue2s(L, L->top, htab); /* put table on stack */ + incr_top(L); + fixedstack(L); for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ - setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); + setobj2n(L, luaH_setnum(L, htab, i+1), L->top - 1 - nvar + i); + unfixedstack(L); /* store counter in field `n' */ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); + L->top--; /* remove table from stack */ } #endif /* move fixed parameters to final position */ @@ -232,11 +243,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { setobjs2s(L, L->top++, fixed+i); setnilvalue(fixed+i); } +#if defined(LUA_COMPAT_VARARG) /* add `arg' parameter */ if (htab) { sethvalue(L, L->top++, htab); lua_assert(iswhite(obj2gco(htab))); } +#endif return base; } @@ -495,6 +508,7 @@ static void f_parser (lua_State *L, void *ud) { struct SParser *p = cast(struct SParser *, ud); int c = luaZ_lookahead(p->z); luaC_checkGC(L); + set_block_gc(L); /* stop collector during parsing */ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, &p->buff, p->name); cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); @@ -503,6 +517,7 @@ static void f_parser (lua_State *L, void *ud) { cl->l.upvals[i] = luaF_newupval(L); setclvalue(L, L->top, cl); incr_top(L); + unset_block_gc(L); } 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) { } 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->next = *pp; /* chain it in the proper position */ *pp = obj2gco(uv); @@ -74,6 +73,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { uv->u.l.next = g->uvhead.u.l.next; uv->u.l.next->u.l.prev = uv; g->uvhead.u.l.next = uv; + luaC_marknew(L, obj2gco(uv)); lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); return uv; } 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 @@ #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) +#ifndef yield + #define yield() {} +#endif static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); @@ -232,8 +235,10 @@ static void traverseclosure (global_State *g, Closure *cl) { int i; lua_assert(cl->l.nupvalues == cl->l.p->nups); markobject(g, cl->l.p); - for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ - markobject(g, cl->l.upvals[i]); + for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ + if(cl->l.upvals[i]) + markobject(g, cl->l.upvals[i]); + } } } @@ -258,6 +263,7 @@ static void traversestack (global_State *g, lua_State *l) { CallInfo *ci; markvalue(g, gt(l)); lim = l->top; + if(l->stack == NULL) return; /* no stack to traverse */ for (ci = l->base_ci; ci <= l->ci; ci++) { lua_assert(ci->top <= l->stack_last); if (lim < ci->top) lim = ci->top; @@ -266,7 +272,8 @@ static void traversestack (global_State *g, lua_State *l) { markvalue(g, o); for (; o <= lim; o++) setnilvalue(o); - checkstacksizes(l, lim); + if (!isfixedstack(l)) /* if stack size is fixed, can't resize it. */ + checkstacksizes(l, lim); } @@ -419,8 +426,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { else { /* must erase `curr' */ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); *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); } } @@ -434,6 +439,8 @@ static void checkSizes (lua_State *L) { if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && g->strt.size > MINSTRTABSIZE*2) luaS_resize(L, g->strt.size/2); /* table is too big */ + /* it is not safe to re-size the buffer if it is in use. */ + if (luaZ_bufflen(&g->buff) > 0) return; /* check size of buffer */ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; @@ -552,6 +559,15 @@ static void atomic (lua_State *L) { g->estimate = g->totalbytes - udsize; /* first estimate */ } +static void sweepstrstep (global_State *g, lua_State *L) { + lu_mem old = g->totalbytes; + sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); + if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ + g->gcstate = GCSsweep; /* end sweep-string phase */ + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; +} + static l_mem singlestep (lua_State *L) { global_State *g = G(L); @@ -570,12 +586,7 @@ static l_mem singlestep (lua_State *L) { } } case GCSsweepstring: { - lu_mem old = g->totalbytes; - sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); - if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ - g->gcstate = GCSsweep; /* end sweep-string phase */ - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; + sweepstrstep(g, L); return GCSWEEPCOST; } case GCSsweep: { @@ -609,10 +620,14 @@ static l_mem singlestep (lua_State *L) { void luaC_step (lua_State *L) { global_State *g = G(L); + if(is_block_gc(L)) return; + set_block_gc(L); l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; if (lim == 0) lim = (MAX_LUMEM-1)/2; /* no limit */ g->gcdept += g->totalbytes - g->GCthreshold; + if (g->estimate > g->totalbytes) + g->estimate = g->totalbytes; do { lim -= singlestep(L); if (g->gcstate == GCSpause) @@ -629,11 +644,23 @@ void luaC_step (lua_State *L) { else { setthreshold(g); } + unset_block_gc(L); } +int luaC_sweepstrgc (lua_State *L) { + global_State *g = G(L); + if (g->gcstate == GCSsweepstring) { + sweepstrstep(g, L); + return (g->gcstate == GCSsweepstring) ? 1 : 0; + } + return 0; +} + void luaC_fullgc (lua_State *L) { global_State *g = G(L); + if(is_block_gc(L)) return; + set_block_gc(L); if (g->gcstate <= GCSpropagate) { /* reset sweep marks to sweep all elements (returning them to white) */ g->sweepstrgc = 0; @@ -649,12 +676,15 @@ void luaC_fullgc (lua_State *L) { while (g->gcstate != GCSfinalize) { lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); singlestep(L); + yield(); } markroot(L); while (g->gcstate != GCSpause) { singlestep(L); + yield(); } setthreshold(g); + unset_block_gc(L); } @@ -682,6 +712,14 @@ void luaC_barrierback (lua_State *L, Table *t) { } +void luaC_marknew (lua_State *L, GCObject *o) { + global_State *g = G(L); + o->gch.marked = luaC_white(g); + if (g->gcstate == GCSpropagate) + reallymarkobject(g, o); /* mark new objects as gray during propagate state. */ +} + + void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { global_State *g = G(L); 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 @@ #define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) +/* +** Possible Garbage Collector flags. +** Layout for bit use in 'gsflags' field in global_State structure. +** bit 0 - Protect GC from recursive calls. +** bit 1 - Don't try to shrink string table if EGC was called during a string table resize. +*/ +#define GCFlagsNone 0 +#define GCBlockGCBit 0 +#define GCResizingStringsBit 1 + + +#define is_block_gc(L) testbit(G(L)->gcflags, GCBlockGCBit) +#define set_block_gc(L) l_setbit(G(L)->gcflags, GCBlockGCBit) +#define unset_block_gc(L) resetbit(G(L)->gcflags, GCBlockGCBit) +#define is_resizing_strings_gc(L) testbit(G(L)->gcflags, GCResizingStringsBit) +#define set_resizing_strings_gc(L) l_setbit(G(L)->gcflags, GCResizingStringsBit) +#define unset_resizing_strings_gc(L) resetbit(G(L)->gcflags, GCResizingStringsBit) /* ** Layout for bit use in `marked' field: ** bit 0 - object is white (type 0) ** bit 1 - object is white (type 1) ** bit 2 - object is black +** bit 3 - for thread: Don't resize thread's stack ** bit 3 - for userdata: has been finalized ** bit 3 - for tables: has weak keys ** bit 4 - for tables: has weak values @@ -54,6 +72,7 @@ #define WHITE0BIT 0 #define WHITE1BIT 1 #define BLACKBIT 2 +#define FIXEDSTACKBIT 3 #define FINALIZEDBIT 3 #define KEYWEAKBIT 3 #define VALUEWEAKBIT 4 @@ -76,6 +95,9 @@ #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) +#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT) +#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT) +#define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT) #define luaC_checkGC(L) { \ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ @@ -101,6 +123,8 @@ LUAI_FUNC void luaC_callGCTM (lua_State *L); LUAI_FUNC void luaC_freeall (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); LUAI_FUNC void luaC_fullgc (lua_State *L); +LUAI_FUNC int luaC_sweepstrgc (lua_State *L); +LUAI_FUNC void luaC_marknew (lua_State *L, GCObject *o); LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); LUAI_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 { #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) #define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } + { lua_Number i_x = (x); TValue *i_o=(obj); i_o->value.n=i_x; i_o->tt=LUA_TNUMBER; } #define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + { void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTUSERDATA; } #define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + { int i_x = (x); TValue *i_o=(obj); i_o->value.b=i_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; \ + { GCObject *i_x = cast(GCObject *, (x)); \ + TValue *i_o=(obj); \ + i_o->value.gc=i_x; i_o->tt=LUA_TSTRING; \ checkliveness(G(L),i_o); } #define setuvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ + { GCObject *i_x = cast(GCObject *, (x)); \ + TValue *i_o=(obj); \ + i_o->value.gc=i_x; i_o->tt=LUA_TUSERDATA; \ checkliveness(G(L),i_o); } #define setthvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ + { GCObject *i_x = cast(GCObject *, (x)); \ + TValue *i_o=(obj); \ + i_o->value.gc=i_x; i_o->tt=LUA_TTHREAD; \ checkliveness(G(L),i_o); } #define setclvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ + { GCObject *i_x = cast(GCObject *, (x)); \ + TValue *i_o=(obj); \ + i_o->value.gc=i_x; i_o->tt=LUA_TFUNCTION; \ checkliveness(G(L),i_o); } #define sethvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ + { GCObject *i_x = cast(GCObject *, (x)); \ + TValue *i_o=(obj); \ + i_o->value.gc=i_x; i_o->tt=LUA_TTABLE; \ checkliveness(G(L),i_o); } #define setptvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + { GCObject *i_x = cast(GCObject *, (x)); \ + TValue *i_o=(obj); \ + i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \ checkliveness(G(L),i_o); } 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) { Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { struct LexState lexstate; struct FuncState funcstate; + TString *tname = luaS_new(L, name); + setsvalue2s(L, L->top, tname); /* protect name */ + incr_top(L); lexstate.buff = buff; - luaX_setinput(L, &lexstate, z, luaS_new(L, name)); + luaX_setinput(L, &lexstate, z, tname); open_func(&lexstate, &funcstate); funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ luaX_next(&lexstate); /* read first token */ chunk(&lexstate); check(&lexstate, TK_EOS); close_func(&lexstate); + L->top--; /* remove 'name' from stack */ lua_assert(funcstate.prev == NULL); lua_assert(funcstate.f->nups == 0); 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) { lua_State *luaE_newthread (lua_State *L) { lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); luaC_link(L, obj2gco(L1), LUA_TTHREAD); + setthvalue(L, L->top, L1); /* put thread on stack */ + incr_top(L); preinit_state(L1, G(L)); stack_init(L1, L); /* init stack */ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ @@ -126,7 +128,8 @@ lua_State *luaE_newthread (lua_State *L) { L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); - lua_assert(iswhite(obj2gco(L1))); + lua_assert(!isdead(G(L), obj2gco(L1))); + L->top--; /* remove thread from stack */ return L1; } @@ -160,6 +163,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->uvhead.u.l.prev = &g->uvhead; g->uvhead.u.l.next = &g->uvhead; g->GCthreshold = 0; /* mark it as unfinished state */ + g->estimate = 0; g->strt.size = 0; g->strt.nuse = 0; g->strt.hash = NULL; @@ -167,6 +171,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { luaZ_initbuffer(L, &g->buff); g->panic = NULL; g->gcstate = GCSpause; + g->gcflags = GCFlagsNone; g->rootgc = obj2gco(L); g->sweepstrgc = 0; 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 { void *ud; /* auxiliary data to `frealloc' */ lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ + lu_byte gcflags; /* flags for the garbage collector */ int sweepstrgc; /* position of sweep in `strt' */ GCObject *rootgc; /* list of all collectable objects */ 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 @@ void luaS_resize (lua_State *L, int newsize) { - GCObject **newhash; stringtable *tb; int i; - if (G(L)->gcstate == GCSsweepstring) - return; /* cannot resize during GC traverse */ - newhash = luaM_newvector(L, newsize, GCObject *); tb = &G(L)->strt; - for (i=0; i<newsize; i++) newhash[i] = NULL; + if (luaC_sweepstrgc(L) || newsize == tb->size || is_resizing_strings_gc(L)) + return; /* cannot resize during GC traverse or doesn't need to be resized */ + set_resizing_strings_gc(L); + if (newsize > tb->size) { + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); + for (i=tb->size; i<newsize; i++) tb->hash[i] = NULL; + } /* rehash */ for (i=0; i<tb->size; i++) { GCObject *p = tb->hash[i]; + tb->hash[i] = NULL; while (p) { /* for each node in the list */ GCObject *next = p->gch.next; /* save next */ unsigned int h = gco2ts(p)->hash; int h1 = lmod(h, newsize); /* new position */ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); - p->gch.next = newhash[h1]; /* chain it */ - newhash[h1] = p; + p->gch.next = tb->hash[h1]; /* chain it */ + tb->hash[h1] = p; p = next; } } - luaM_freearray(L, tb->hash, tb->size, TString *); + if (newsize < tb->size) + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); tb->size = newsize; - tb->hash = newhash; + unset_resizing_strings_gc(L); } @@ -55,6 +59,9 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, stringtable *tb; if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof("")) luaM_toobig(L); + tb = &G(L)->strt; + if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ ts = cast(TString *, luaM_malloc(L, sizetstring(type, l))); ts->tsv.len = l; ts->tsv.hash = h; @@ -70,13 +77,10 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, 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 */ tb->hash[h] = obj2gco(ts); tb->nuse++; - if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) - luaS_resize(L, tb->size*2); /* too crowded */ return ts; } 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) { Table *luaH_new (lua_State *L, int narray, int nhash) { Table *t = luaM_new(L, Table); luaC_link(L, obj2gco(t), LUA_TTABLE); + sethvalue2s(L, L->top, t); /* put table on stack */ + incr_top(L); t->metatable = NULL; t->flags = cast_byte(~0); /* temporary values (kept only if some malloc fails) */ @@ -367,6 +369,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) { t->node = cast(Node *, dummynode); setarrayvector(L, t, narray); setnodevector(L, t, nhash); + L->top--; /* remove table from stack */ return t; } 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 @@ +#include "plugin.h" +#include "lstate.h" +#include LUA_USER_H + +/* lua Out Of Memory */ +static struct lua_OOM l_oom = {NULL, 0}; + +int set_lua_OOM(lua_State * L) +{ + l_oom.L = L; + l_oom.count++; + return 0; +} + +struct lua_OOM *get_lua_OOM(void) +{ + return &l_oom; +} 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 @@ +#ifndef _LUA_USER_H_ +#define _LUA_USER_H_ + +#define LUA_OOM(L) set_lua_OOM(L) + +struct lua_OOM { + lua_State * L; + int count; +}; + +int set_lua_OOM(lua_State * L); + +struct lua_OOM* get_lua_OOM(void); +#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); /*Rocklua functions*/ #include "rockconf.h" +/* heap */ +#undef LUAI_GCPAUSE /*200*/ +#define LUAI_GCPAUSE 125 +#define MINSTRTABSIZE 512 /*32*/ + /*else*/ +#define LUA_USER_H "lua_user.h" #define LUA_DISABLE_BYTECODE #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) { return 0; else { char s[LUAI_MAXNUMBER2STR]; + ptrdiff_t objr = savestack(L, obj); lua_Number n = nvalue(obj); lua_number2str(s, n); - setsvalue2s(L, obj, luaS_new(L, s)); + setsvalue2s(L, restorestack(L, objr), luaS_new(L, s)); return 1; } } @@ -134,6 +135,9 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { int loop; TValue temp; + setnilvalue(L->top); + L->top++; + fixedstack(L); for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ @@ -141,6 +145,8 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ if (!ttisnil(oldval) || /* result is no nil? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + L->top--; + unfixedstack(L); setobj2t(L, oldval, val); h->flags = 0; luaC_barriert(L, h, val); @@ -151,12 +157,15 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) luaG_typeerror(L, t, "index"); if (ttisfunction(tm)) { + L->top--; + unfixedstack(L); callTM(L, tm, t, key, val); return; } /* else repeat with `tm' */ setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ t = &temp; + setobj2s(L, L->top-1, t); /* need to protect value from EGC. */ } luaG_runerror(L, "loop in settable"); } @@ -284,8 +293,11 @@ void luaV_concat (lua_State *L, int total, int last) { StkId top = L->base + last + 1; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) { + /* restore 'top' pointer, since stack might have been reallocted */ + top = L->base + last + 1; luaG_concaterror(L, top-2, top-1); + } } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ (void)tostring(L, top - 2); /* result is first op (as string) */ else { @@ -293,12 +305,14 @@ void luaV_concat (lua_State *L, int total, int last) { size_t tl = tsvalue(top-1)->len; char *buffer; int i; + fixedstack(L); /* collect total length */ for (n = 1; n < total && tostring(L, top-n-1); n++) { size_t l = tsvalue(top-n-1)->len; if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); tl += l; } + G(L)->buff.n = tl; buffer = luaZ_openspace(L, &G(L)->buff, tl); tl = 0; for (i=n; i>0; i--) { /* concat all strings */ @@ -307,6 +321,8 @@ void luaV_concat (lua_State *L, int total, int last) { tl += l; } setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + luaZ_resetbuffer(&G(L)->buff); + unfixedstack(L); } total -= n-1; /* got `n' strings to create 1 new */ last -= n-1; @@ -332,8 +348,13 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, default: lua_assert(0); break; } } - else if (!call_binTM(L, rb, rc, ra, op)) - luaG_aritherror(L, rb, rc); + else { + ptrdiff_t br = savestack(L, rb); + ptrdiff_t cr = savestack(L, rc); + if (!call_binTM(L, rb, rc, ra, op)) { + luaG_aritherror(L, restorestack(L, br), restorestack(L, cr)); + } + } } @@ -461,7 +482,9 @@ void luaV_execute (lua_State *L, int nexeccalls) { case OP_NEWTABLE: { int b = GETARG_B(i); int c = GETARG_C(i); - sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); + Table *h; + Protect(h = luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); + sethvalue(L, RA(i), h); Protect(luaC_checkGC(L)); continue; } @@ -547,9 +570,10 @@ void luaV_execute (lua_State *L, int nexeccalls) { break; } default: { /* try metamethod */ + ptrdiff_t br = savestack(L, rb); Protect( if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) - luaG_typeerror(L, rb, "get length of"); + luaG_typeerror(L, restorestack(L, br), "get length of"); ) } } @@ -723,6 +747,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { int c = GETARG_C(i); int last; Table *h; + fixedstack(L); if (n == 0) { n = cast_int(L->top - ra) - 1; L->top = L->ci->top; @@ -738,6 +763,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { setobj2t(L, luaH_setnum(L, h, last--), val); luaC_barriert(L, h, val); } + unfixedstack(L); continue; } case OP_CLOSE: { @@ -750,7 +776,9 @@ void luaV_execute (lua_State *L, int nexeccalls) { int nup, j; p = cl->p->p[GETARG_Bx(i)]; nup = p->nups; + fixedstack(L); ncl = luaF_newLclosure(L, nup, cl->env); + setclvalue(L, ra, ncl); ncl->l.p = p; for (j=0; j<nup; j++, pc++) { if (GET_OPCODE(*pc) == OP_GETUPVAL) @@ -760,7 +788,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); } } - setclvalue(L, ra, ncl); + unfixedstack(L); Protect(luaC_checkGC(L)); continue; } 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 { size_t buffsize; } Mbuffer; -#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->n = 0, (buff)->buffsize = 0) #define luaZ_buffer(buff) ((buff)->buffer) #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); #define strcmp rb->strcmp #define strcpy rb->strcpy #define strlen rb->strlen +#define yield() rb->yield() #endif /* _ROCKCONF_H_ */ 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) break; } - rb->yield(); + yield(); lua_pushinteger(L, result); return 1; } @@ -382,7 +382,7 @@ RB_WRAP(audio) return 1; } - rb->yield(); + yield(); lua_pushinteger(L, status); /* return previous (or current) audio status */ return 1; } @@ -502,7 +502,7 @@ RB_WRAP(pcm) break; } - rb->yield(); + yield(); return 1; } 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 @@ #include "plugin.h" #include <tlsf.h> +#include "lua.h" void *get_new_area(size_t *size) { @@ -36,7 +37,8 @@ void *get_new_area(size_t *size) return pluginbuf_ptr; } - if (audiobuf_ptr == NULL) + /* only grab the next area if lua already tried + failed to garbage collect*/ + if (audiobuf_ptr == NULL && (get_lua_OOM())->count > 0) { /* grab audiobuffer */ audiobuf_ptr = rb->plugin_get_audio_buffer(size); |