1
0
Fork 0
forked from len0rd/rockbox

Lua Add Emergency Garbage Collector

Derivative of work by RobertGabrielJakabosky
 http://lua-users.org/wiki/EmergencyGarbageCollector

I've only implemented the not enough memory part and
 expanded this idea to adding a mechanism to signal
 the OOM condition of the plugin buffer which allows us to only
 grab the playback buffer after garbage collection fails
 (SO THE MUSIC KEEPS PLAYING AS LONG AS POSSIBLE)

Change-Id: I684fb98b540ffc01f7ba324ab5b761ceb59b9f9b
This commit is contained in:
William Wilgus 2019-07-12 05:23:52 -05:00
parent 4beafe16fa
commit 45bd14b392
21 changed files with 266 additions and 68 deletions

View file

@ -24,6 +24,7 @@ ltable.c
ltablib.c ltablib.c
ltm.c ltm.c
lundump.c lundump.c
lua_user.c
lvm.c lvm.c
lzio.c lzio.c
rockaux.c rockaux.c

View file

@ -547,7 +547,9 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
lua_lock(L); lua_lock(L);
t = index2adr(L, idx); t = index2adr(L, idx);
api_checkvalidindex(L, t); api_checkvalidindex(L, t);
fixedstack(L);
setsvalue(L, &key, luaS_new(L, k)); setsvalue(L, &key, luaS_new(L, k));
unfixedstack(L);
luaV_gettable(L, t, &key, L->top); luaV_gettable(L, t, &key, L->top);
api_incr_top(L); api_incr_top(L);
lua_unlock(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) { LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
StkId t; StkId t;
TValue key;
lua_lock(L); lua_lock(L);
api_checknelems(L, 1); api_checknelems(L, 1);
t = index2adr(L, idx); t = index2adr(L, idx);
api_checkvalidindex(L, t); api_checkvalidindex(L, t);
setsvalue(L, &key, luaS_new(L, k)); setsvalue2s(L, L->top, luaS_new(L, k));
luaV_settable(L, t, &key, L->top - 1); api_incr_top(L);
L->top--; /* pop value */ luaV_settable(L, t, L->top - 1, L->top - 2);
L->top -= 2; /* pop key and value */
lua_unlock(L); lua_unlock(L);
} }
@ -674,7 +676,9 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
api_checknelems(L, 2); api_checknelems(L, 2);
t = index2adr(L, idx); t = index2adr(L, idx);
api_check(L, ttistable(t)); api_check(L, ttistable(t));
fixedstack(L);
setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
unfixedstack(L);
luaC_barriert(L, hvalue(t), L->top-1); luaC_barriert(L, hvalue(t), L->top-1);
L->top -= 2; L->top -= 2;
lua_unlock(L); lua_unlock(L);
@ -687,7 +691,9 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
api_checknelems(L, 1); api_checknelems(L, 1);
o = index2adr(L, idx); o = index2adr(L, idx);
api_check(L, ttistable(o)); api_check(L, ttistable(o));
fixedstack(L);
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
unfixedstack(L);
luaC_barriert(L, hvalue(o), L->top-1); luaC_barriert(L, hvalue(o), L->top-1);
L->top--; L->top--;
lua_unlock(L); lua_unlock(L);
@ -903,11 +909,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
g = G(L); g = G(L);
switch (what) { switch (what) {
case LUA_GCSTOP: { case LUA_GCSTOP: {
g->GCthreshold = MAX_LUMEM; set_block_gc(L);
break; break;
} }
case LUA_GCRESTART: { case LUA_GCRESTART: {
g->GCthreshold = g->totalbytes; unset_block_gc(L);
break; break;
} }
case LUA_GCCOLLECT: { case LUA_GCCOLLECT: {
@ -924,6 +930,10 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
break; break;
} }
case LUA_GCSTEP: { 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); lu_mem a = (cast(lu_mem, data) << 10);
if (a <= g->totalbytes) if (a <= g->totalbytes)
g->GCthreshold = g->totalbytes - a; g->GCthreshold = g->totalbytes - a;

View file

@ -13,7 +13,6 @@
#include <string.h> #include <string.h>
#include "lstring.h" /* ROCKLUA ADDED */ #include "lstring.h" /* ROCKLUA ADDED */
/* This file uses only the official API of Lua. /* This file uses only the official API of Lua.
** Any function declared here could be written as an application function. ** Any function declared here could be written as an application function.
** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED ** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED
@ -34,7 +33,9 @@
#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
lua_gettop(L) + (i) + 1) lua_gettop(L) + (i) + 1)
#ifndef LUA_OOM
#define LUA_OOM(L) {}
#endif
/* /*
** {====================================================== ** {======================================================
** Error-report functions ** 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) { 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) { if (nsize == 0) {
free(ptr); free(ptr);
return NULL; 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) { LUALIB_API lua_State *luaL_newstate (void) {
lua_State *L = lua_newstate(l_alloc, NULL); lua_State *L = lua_newstate(l_alloc, NULL);
lua_setallocf(L, l_alloc, L); /* allocator needs lua_State. */
if (L) lua_atpanic(L, &panic); if (L) lua_atpanic(L, &panic);
return L; return L;
} }

View file

@ -51,11 +51,13 @@ struct lua_longjmp {
void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) { switch (errcode) {
case LUA_ERRMEM: { 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; break;
} }
case LUA_ERRERR: { 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; break;
} }
case LUA_ERRSYNTAX: case LUA_ERRSYNTAX:
@ -92,6 +94,8 @@ static void resetstack (lua_State *L, int status) {
void luaD_throw (lua_State *L, int errcode) { 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) { if (L->errorJmp) {
L->errorJmp->status = errcode; L->errorJmp->status = errcode;
LUAI_THROW(L, L->errorJmp); 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) { static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
int i; int i;
int nfixargs = p->numparams; int nfixargs = p->numparams;
#if defined(LUA_COMPAT_VARARG)
Table *htab = NULL; Table *htab = NULL;
#endif
StkId base, fixed; StkId base, fixed;
for (; actual < nfixargs; ++actual) for (; actual < nfixargs; ++actual)
setnilvalue(L->top++); setnilvalue(L->top++);
@ -219,10 +225,15 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
luaC_checkGC(L); luaC_checkGC(L);
luaD_checkstack(L, p->maxstacksize); luaD_checkstack(L, p->maxstacksize);
htab = luaH_new(L, nvar, 1); /* create `arg' table */ 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 */ 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' */ /* store counter in field `n' */
setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
L->top--; /* remove table from stack */
} }
#endif #endif
/* move fixed parameters to final position */ /* 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); setobjs2s(L, L->top++, fixed+i);
setnilvalue(fixed+i); setnilvalue(fixed+i);
} }
#if defined(LUA_COMPAT_VARARG)
/* add `arg' parameter */ /* add `arg' parameter */
if (htab) { if (htab) {
sethvalue(L, L->top++, htab); sethvalue(L, L->top++, htab);
lua_assert(iswhite(obj2gco(htab))); lua_assert(iswhite(obj2gco(htab)));
} }
#endif
return base; return base;
} }
@ -495,6 +508,7 @@ static void f_parser (lua_State *L, void *ud) {
struct SParser *p = cast(struct SParser *, ud); struct SParser *p = cast(struct SParser *, ud);
int c = luaZ_lookahead(p->z); int c = luaZ_lookahead(p->z);
luaC_checkGC(L); luaC_checkGC(L);
set_block_gc(L); /* stop collector during parsing */
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
&p->buff, p->name); &p->buff, p->name);
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); 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); cl->l.upvals[i] = luaF_newupval(L);
setclvalue(L, L->top, cl); setclvalue(L, L->top, cl);
incr_top(L); incr_top(L);
unset_block_gc(L);
} }

View file

@ -66,7 +66,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
} }
uv = luaM_new(L, UpVal); /* not found: create a new one */ uv = luaM_new(L, UpVal); /* not found: create a new one */
uv->tt = LUA_TUPVAL; uv->tt = LUA_TUPVAL;
uv->marked = luaC_white(g);
uv->v = level; /* current value lives in the stack */ uv->v = level; /* current value lives in the stack */
uv->next = *pp; /* chain it in the proper position */ uv->next = *pp; /* chain it in the proper position */
*pp = obj2gco(uv); *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 = g->uvhead.u.l.next;
uv->u.l.next->u.l.prev = uv; uv->u.l.next->u.l.prev = uv;
g->uvhead.u.l.next = 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); lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
return uv; return uv;
} }

View file

@ -58,6 +58,9 @@
#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
#ifndef yield
#define yield() {}
#endif
static void removeentry (Node *n) { static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n))); lua_assert(ttisnil(gval(n)));
@ -232,9 +235,11 @@ static void traverseclosure (global_State *g, Closure *cl) {
int i; int i;
lua_assert(cl->l.nupvalues == cl->l.p->nups); lua_assert(cl->l.nupvalues == cl->l.p->nups);
markobject(g, cl->l.p); markobject(g, cl->l.p);
for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
if(cl->l.upvals[i])
markobject(g, 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; CallInfo *ci;
markvalue(g, gt(l)); markvalue(g, gt(l));
lim = l->top; lim = l->top;
if(l->stack == NULL) return; /* no stack to traverse */
for (ci = l->base_ci; ci <= l->ci; ci++) { for (ci = l->base_ci; ci <= l->ci; ci++) {
lua_assert(ci->top <= l->stack_last); lua_assert(ci->top <= l->stack_last);
if (lim < ci->top) lim = ci->top; if (lim < ci->top) lim = ci->top;
@ -266,6 +272,7 @@ static void traversestack (global_State *g, lua_State *l) {
markvalue(g, o); markvalue(g, o);
for (; o <= lim; o++) for (; o <= lim; o++)
setnilvalue(o); setnilvalue(o);
if (!isfixedstack(l)) /* if stack size is fixed, can't resize it. */
checkstacksizes(l, lim); checkstacksizes(l, lim);
} }
@ -419,8 +426,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
else { /* must erase `curr' */ else { /* must erase `curr' */
lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
*p = curr->gch.next; *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); freeobj(L, curr);
} }
} }
@ -434,6 +439,8 @@ static void checkSizes (lua_State *L) {
if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
g->strt.size > MINSTRTABSIZE*2) g->strt.size > MINSTRTABSIZE*2)
luaS_resize(L, g->strt.size/2); /* table is too big */ 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 */ /* check size of buffer */
if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
size_t newsize = luaZ_sizebuffer(&g->buff) / 2; 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 */ 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) { static l_mem singlestep (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
@ -570,12 +586,7 @@ static l_mem singlestep (lua_State *L) {
} }
} }
case GCSsweepstring: { case GCSsweepstring: {
lu_mem old = g->totalbytes; sweepstrstep(g, L);
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;
return GCSWEEPCOST; return GCSWEEPCOST;
} }
case GCSsweep: { case GCSsweep: {
@ -609,10 +620,14 @@ static l_mem singlestep (lua_State *L) {
void luaC_step (lua_State *L) { void luaC_step (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
if(is_block_gc(L)) return;
set_block_gc(L);
l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
if (lim == 0) if (lim == 0)
lim = (MAX_LUMEM-1)/2; /* no limit */ lim = (MAX_LUMEM-1)/2; /* no limit */
g->gcdept += g->totalbytes - g->GCthreshold; g->gcdept += g->totalbytes - g->GCthreshold;
if (g->estimate > g->totalbytes)
g->estimate = g->totalbytes;
do { do {
lim -= singlestep(L); lim -= singlestep(L);
if (g->gcstate == GCSpause) if (g->gcstate == GCSpause)
@ -629,11 +644,23 @@ void luaC_step (lua_State *L) {
else { else {
setthreshold(g); 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) { void luaC_fullgc (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
if(is_block_gc(L)) return;
set_block_gc(L);
if (g->gcstate <= GCSpropagate) { if (g->gcstate <= GCSpropagate) {
/* reset sweep marks to sweep all elements (returning them to white) */ /* reset sweep marks to sweep all elements (returning them to white) */
g->sweepstrgc = 0; g->sweepstrgc = 0;
@ -649,12 +676,15 @@ void luaC_fullgc (lua_State *L) {
while (g->gcstate != GCSfinalize) { while (g->gcstate != GCSfinalize) {
lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
singlestep(L); singlestep(L);
yield();
} }
markroot(L); markroot(L);
while (g->gcstate != GCSpause) { while (g->gcstate != GCSpause) {
singlestep(L); singlestep(L);
yield();
} }
setthreshold(g); 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) { void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
global_State *g = G(L); global_State *g = G(L);
o->gch.next = g->rootgc; o->gch.next = g->rootgc;

View file

@ -37,12 +37,30 @@
#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) #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: ** Layout for bit use in `marked' field:
** bit 0 - object is white (type 0) ** bit 0 - object is white (type 0)
** bit 1 - object is white (type 1) ** bit 1 - object is white (type 1)
** bit 2 - object is black ** 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 userdata: has been finalized
** bit 3 - for tables: has weak keys ** bit 3 - for tables: has weak keys
** bit 4 - for tables: has weak values ** bit 4 - for tables: has weak values
@ -54,6 +72,7 @@
#define WHITE0BIT 0 #define WHITE0BIT 0
#define WHITE1BIT 1 #define WHITE1BIT 1
#define BLACKBIT 2 #define BLACKBIT 2
#define FIXEDSTACKBIT 3
#define FINALIZEDBIT 3 #define FINALIZEDBIT 3
#define KEYWEAKBIT 3 #define KEYWEAKBIT 3
#define VALUEWEAKBIT 4 #define VALUEWEAKBIT 4
@ -76,6 +95,9 @@
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #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) { \ #define luaC_checkGC(L) { \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ 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_freeall (lua_State *L);
LUAI_FUNC void luaC_step (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L);
LUAI_FUNC void luaC_fullgc (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_link (lua_State *L, GCObject *o, lu_byte tt);
LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);

View file

@ -117,42 +117,48 @@ typedef struct lua_TValue {
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
#define setnvalue(obj,x) \ #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) \ #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) \ #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) \ #define setsvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { GCObject *i_x = cast(GCObject *, (x)); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TSTRING; \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }
#define setuvalue(L,obj,x) \ #define setuvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { GCObject *i_x = cast(GCObject *, (x)); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TUSERDATA; \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }
#define setthvalue(L,obj,x) \ #define setthvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { GCObject *i_x = cast(GCObject *, (x)); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TTHREAD; \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }
#define setclvalue(L,obj,x) \ #define setclvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { GCObject *i_x = cast(GCObject *, (x)); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TFUNCTION; \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }
#define sethvalue(L,obj,x) \ #define sethvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { GCObject *i_x = cast(GCObject *, (x)); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TTABLE; \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }
#define setptvalue(L,obj,x) \ #define setptvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { GCObject *i_x = cast(GCObject *, (x)); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }

View file

@ -383,14 +383,18 @@ static void close_func (LexState *ls) {
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
struct LexState lexstate; struct LexState lexstate;
struct FuncState funcstate; struct FuncState funcstate;
TString *tname = luaS_new(L, name);
setsvalue2s(L, L->top, tname); /* protect name */
incr_top(L);
lexstate.buff = buff; lexstate.buff = buff;
luaX_setinput(L, &lexstate, z, luaS_new(L, name)); luaX_setinput(L, &lexstate, z, tname);
open_func(&lexstate, &funcstate); open_func(&lexstate, &funcstate);
funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
luaX_next(&lexstate); /* read first token */ luaX_next(&lexstate); /* read first token */
chunk(&lexstate); chunk(&lexstate);
check(&lexstate, TK_EOS); check(&lexstate, TK_EOS);
close_func(&lexstate); close_func(&lexstate);
L->top--; /* remove 'name' from stack */
lua_assert(funcstate.prev == NULL); lua_assert(funcstate.prev == NULL);
lua_assert(funcstate.f->nups == 0); lua_assert(funcstate.f->nups == 0);
lua_assert(lexstate.fs == NULL); lua_assert(lexstate.fs == NULL);

View file

@ -119,6 +119,8 @@ static void close_state (lua_State *L) {
lua_State *luaE_newthread (lua_State *L) { lua_State *luaE_newthread (lua_State *L) {
lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
luaC_link(L, obj2gco(L1), LUA_TTHREAD); luaC_link(L, obj2gco(L1), LUA_TTHREAD);
setthvalue(L, L->top, L1); /* put thread on stack */
incr_top(L);
preinit_state(L1, G(L)); preinit_state(L1, G(L));
stack_init(L1, L); /* init stack */ stack_init(L1, L); /* init stack */
setobj2n(L, gt(L1), gt(L)); /* share table of globals */ 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->basehookcount = L->basehookcount;
L1->hook = L->hook; L1->hook = L->hook;
resethookcount(L1); resethookcount(L1);
lua_assert(iswhite(obj2gco(L1))); lua_assert(!isdead(G(L), obj2gco(L1)));
L->top--; /* remove thread from stack */
return L1; 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.prev = &g->uvhead;
g->uvhead.u.l.next = &g->uvhead; g->uvhead.u.l.next = &g->uvhead;
g->GCthreshold = 0; /* mark it as unfinished state */ g->GCthreshold = 0; /* mark it as unfinished state */
g->estimate = 0;
g->strt.size = 0; g->strt.size = 0;
g->strt.nuse = 0; g->strt.nuse = 0;
g->strt.hash = NULL; g->strt.hash = NULL;
@ -167,6 +171,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
luaZ_initbuffer(L, &g->buff); luaZ_initbuffer(L, &g->buff);
g->panic = NULL; g->panic = NULL;
g->gcstate = GCSpause; g->gcstate = GCSpause;
g->gcflags = GCFlagsNone;
g->rootgc = obj2gco(L); g->rootgc = obj2gco(L);
g->sweepstrgc = 0; g->sweepstrgc = 0;
g->sweepgc = &g->rootgc; g->sweepgc = &g->rootgc;

View file

@ -71,6 +71,7 @@ typedef struct global_State {
void *ud; /* auxiliary data to `frealloc' */ void *ud; /* auxiliary data to `frealloc' */
lu_byte currentwhite; lu_byte currentwhite;
lu_byte gcstate; /* state of garbage collector */ lu_byte gcstate; /* state of garbage collector */
lu_byte gcflags; /* flags for the garbage collector */
int sweepstrgc; /* position of sweep in `strt' */ int sweepstrgc; /* position of sweep in `strt' */
GCObject *rootgc; /* list of all collectable objects */ GCObject *rootgc; /* list of all collectable objects */
GCObject **sweepgc; /* position of sweep in `rootgc' */ GCObject **sweepgc; /* position of sweep in `rootgc' */

View file

@ -22,30 +22,34 @@
void luaS_resize (lua_State *L, int newsize) { void luaS_resize (lua_State *L, int newsize) {
GCObject **newhash;
stringtable *tb; stringtable *tb;
int i; int i;
if (G(L)->gcstate == GCSsweepstring)
return; /* cannot resize during GC traverse */
newhash = luaM_newvector(L, newsize, GCObject *);
tb = &G(L)->strt; 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 */ /* rehash */
for (i=0; i<tb->size; i++) { for (i=0; i<tb->size; i++) {
GCObject *p = tb->hash[i]; GCObject *p = tb->hash[i];
tb->hash[i] = NULL;
while (p) { /* for each node in the list */ while (p) { /* for each node in the list */
GCObject *next = p->gch.next; /* save next */ GCObject *next = p->gch.next; /* save next */
unsigned int h = gco2ts(p)->hash; unsigned int h = gco2ts(p)->hash;
int h1 = lmod(h, newsize); /* new position */ int h1 = lmod(h, newsize); /* new position */
lua_assert(cast_int(h%newsize) == lmod(h, newsize)); lua_assert(cast_int(h%newsize) == lmod(h, newsize));
p->gch.next = newhash[h1]; /* chain it */ p->gch.next = tb->hash[h1]; /* chain it */
newhash[h1] = p; tb->hash[h1] = p;
p = next; 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->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; stringtable *tb;
if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof("")) if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof(""))
luaM_toobig(L); 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 = cast(TString *, luaM_malloc(L, sizetstring(type, l)));
ts->tsv.len = l; ts->tsv.len = l;
ts->tsv.hash = h; 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)); memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */ ((char *)(ts+1))[l] = '\0'; /* ending 0 */
} }
tb = &G(L)->strt;
h = lmod(h, tb->size); h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */ ts->tsv.next = tb->hash[h]; /* chain new entry */
tb->hash[h] = obj2gco(ts); tb->hash[h] = obj2gco(ts);
tb->nuse++; 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; return ts;
} }

View file

@ -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 *luaH_new (lua_State *L, int narray, int nhash) {
Table *t = luaM_new(L, Table); Table *t = luaM_new(L, Table);
luaC_link(L, obj2gco(t), LUA_TTABLE); luaC_link(L, obj2gco(t), LUA_TTABLE);
sethvalue2s(L, L->top, t); /* put table on stack */
incr_top(L);
t->metatable = NULL; t->metatable = NULL;
t->flags = cast_byte(~0); t->flags = cast_byte(~0);
/* temporary values (kept only if some malloc fails) */ /* 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); t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray); setarrayvector(L, t, narray);
setnodevector(L, t, nhash); setnodevector(L, t, nhash);
L->top--; /* remove table from stack */
return t; return t;
} }

View file

@ -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;
}

View file

@ -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

View file

@ -810,7 +810,13 @@ extern long rb_pow(long, long);
/*Rocklua functions*/ /*Rocklua functions*/
#include "rockconf.h" #include "rockconf.h"
/* heap */
#undef LUAI_GCPAUSE /*200*/
#define LUAI_GCPAUSE 125
#define MINSTRTABSIZE 512 /*32*/
/*else*/ /*else*/
#define LUA_USER_H "lua_user.h"
#define LUA_DISABLE_BYTECODE #define LUA_DISABLE_BYTECODE
#endif #endif

View file

@ -49,9 +49,10 @@ int luaV_tostring (lua_State *L, StkId obj) {
return 0; return 0;
else { else {
char s[LUAI_MAXNUMBER2STR]; char s[LUAI_MAXNUMBER2STR];
ptrdiff_t objr = savestack(L, obj);
lua_Number n = nvalue(obj); lua_Number n = nvalue(obj);
lua_number2str(s, n); lua_number2str(s, n);
setsvalue2s(L, obj, luaS_new(L, s)); setsvalue2s(L, restorestack(L, objr), luaS_new(L, s));
return 1; 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) { void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
int loop; int loop;
TValue temp; TValue temp;
setnilvalue(L->top);
L->top++;
fixedstack(L);
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm; const TValue *tm;
if (ttistable(t)) { /* `t' is a table? */ 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 */ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if (!ttisnil(oldval) || /* result is no nil? */ if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
L->top--;
unfixedstack(L);
setobj2t(L, oldval, val); setobj2t(L, oldval, val);
h->flags = 0; h->flags = 0;
luaC_barriert(L, h, val); 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))) else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index"); luaG_typeerror(L, t, "index");
if (ttisfunction(tm)) { if (ttisfunction(tm)) {
L->top--;
unfixedstack(L);
callTM(L, tm, t, key, val); callTM(L, tm, t, key, val);
return; return;
} }
/* else repeat with `tm' */ /* else repeat with `tm' */
setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */
t = &temp; t = &temp;
setobj2s(L, L->top-1, t); /* need to protect value from EGC. */
} }
luaG_runerror(L, "loop in settable"); 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; StkId top = L->base + last + 1;
int n = 2; /* number of elements handled in this pass (at least 2) */ 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 (!(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); luaG_concaterror(L, top-2, top-1);
}
} else if (tsvalue(top-1)->len == 0) /* second op is empty? */ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
(void)tostring(L, top - 2); /* result is first op (as string) */ (void)tostring(L, top - 2); /* result is first op (as string) */
else { else {
@ -293,12 +305,14 @@ void luaV_concat (lua_State *L, int total, int last) {
size_t tl = tsvalue(top-1)->len; size_t tl = tsvalue(top-1)->len;
char *buffer; char *buffer;
int i; int i;
fixedstack(L);
/* collect total length */ /* collect total length */
for (n = 1; n < total && tostring(L, top-n-1); n++) { for (n = 1; n < total && tostring(L, top-n-1); n++) {
size_t l = tsvalue(top-n-1)->len; size_t l = tsvalue(top-n-1)->len;
if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
tl += l; tl += l;
} }
G(L)->buff.n = tl;
buffer = luaZ_openspace(L, &G(L)->buff, tl); buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0; tl = 0;
for (i=n; i>0; i--) { /* concat all strings */ 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; tl += l;
} }
setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); 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 */ total -= n-1; /* got `n' strings to create 1 new */
last -= n-1; last -= n-1;
@ -332,8 +348,13 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
default: lua_assert(0); break; default: lua_assert(0); break;
} }
} }
else if (!call_binTM(L, rb, rc, ra, op)) else {
luaG_aritherror(L, rb, rc); 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: { case OP_NEWTABLE: {
int b = GETARG_B(i); int b = GETARG_B(i);
int c = GETARG_C(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)); Protect(luaC_checkGC(L));
continue; continue;
} }
@ -547,9 +570,10 @@ void luaV_execute (lua_State *L, int nexeccalls) {
break; break;
} }
default: { /* try metamethod */ default: { /* try metamethod */
ptrdiff_t br = savestack(L, rb);
Protect( Protect(
if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) 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 c = GETARG_C(i);
int last; int last;
Table *h; Table *h;
fixedstack(L);
if (n == 0) { if (n == 0) {
n = cast_int(L->top - ra) - 1; n = cast_int(L->top - ra) - 1;
L->top = L->ci->top; 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); setobj2t(L, luaH_setnum(L, h, last--), val);
luaC_barriert(L, h, val); luaC_barriert(L, h, val);
} }
unfixedstack(L);
continue; continue;
} }
case OP_CLOSE: { case OP_CLOSE: {
@ -750,7 +776,9 @@ void luaV_execute (lua_State *L, int nexeccalls) {
int nup, j; int nup, j;
p = cl->p->p[GETARG_Bx(i)]; p = cl->p->p[GETARG_Bx(i)];
nup = p->nups; nup = p->nups;
fixedstack(L);
ncl = luaF_newLclosure(L, nup, cl->env); ncl = luaF_newLclosure(L, nup, cl->env);
setclvalue(L, ra, ncl);
ncl->l.p = p; ncl->l.p = p;
for (j=0; j<nup; j++, pc++) { for (j=0; j<nup; j++, pc++) {
if (GET_OPCODE(*pc) == OP_GETUPVAL) 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)); ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
} }
} }
setclvalue(L, ra, ncl); unfixedstack(L);
Protect(luaC_checkGC(L)); Protect(luaC_checkGC(L));
continue; continue;
} }

View file

@ -27,7 +27,7 @@ typedef struct Mbuffer {
size_t buffsize; size_t buffsize;
} Mbuffer; } 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_buffer(buff) ((buff)->buffer)
#define luaZ_sizebuffer(buff) ((buff)->buffsize) #define luaZ_sizebuffer(buff) ((buff)->buffsize)

View file

@ -63,6 +63,7 @@ long lpow(long x, long y);
#define strcmp rb->strcmp #define strcmp rb->strcmp
#define strcpy rb->strcpy #define strcpy rb->strcpy
#define strlen rb->strlen #define strlen rb->strlen
#define yield() rb->yield()
#endif /* _ROCKCONF_H_ */ #endif /* _ROCKCONF_H_ */

View file

@ -304,7 +304,7 @@ RB_WRAP(playlist)
break; break;
} }
rb->yield(); yield();
lua_pushinteger(L, result); lua_pushinteger(L, result);
return 1; return 1;
} }
@ -382,7 +382,7 @@ RB_WRAP(audio)
return 1; return 1;
} }
rb->yield(); yield();
lua_pushinteger(L, status); /* return previous (or current) audio status */ lua_pushinteger(L, status); /* return previous (or current) audio status */
return 1; return 1;
} }
@ -502,7 +502,7 @@ RB_WRAP(pcm)
break; break;
} }
rb->yield(); yield();
return 1; return 1;
} }

View file

@ -20,6 +20,7 @@
#include "plugin.h" #include "plugin.h"
#include <tlsf.h> #include <tlsf.h>
#include "lua.h"
void *get_new_area(size_t *size) void *get_new_area(size_t *size)
{ {
@ -36,7 +37,8 @@ void *get_new_area(size_t *size)
return pluginbuf_ptr; 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 */ /* grab audiobuffer */
audiobuf_ptr = rb->plugin_get_audio_buffer(size); audiobuf_ptr = rb->plugin_get_audio_buffer(size);