summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-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
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);