| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- --- a/src/lapi.c
- +++ b/src/lapi.c
- @@ -716,14 +716,14 @@
-
- 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);
- }
-
- @@ -971,7 +971,12 @@
- break;
- }
- case LUA_GCCOLLECT: {
- - luaC_fullgc(L);
- + lu_mem old_thres = g->GCthreshold;
- + if(g->GCthreshold != MAX_LUMEM) {
- + g->GCthreshold = MAX_LUMEM;
- + luaC_fullgc(L);
- + g->GCthreshold = old_thres;
- + }
- break;
- }
- case LUA_GCCOUNT: {
- --- a/src/ldo.c
- +++ b/src/ldo.c
- @@ -494,6 +494,7 @@
- struct SParser *p = cast(struct SParser *, ud);
- int c = luaZ_lookahead(p->z);
- luaC_checkGC(L);
- + lua_gc(L, LUA_GCSTOP, 0); /* 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)));
- @@ -502,6 +503,7 @@
- cl->l.upvals[i] = luaF_newupval(L);
- setclvalue(L, L->top, cl);
- incr_top(L);
- + lua_gc(L, LUA_GCRESTART, 0);
- }
-
-
- --- a/src/lgc.c
- +++ b/src/lgc.c
- @@ -437,7 +437,10 @@
- /* check size of buffer */
- if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
- size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
- - luaZ_resizebuffer(L, &g->buff, newsize);
- + /* make sure newsize is larger then the buffer's in use size. */
- + newsize = (luaZ_bufflen(&g->buff) > newsize) ? luaZ_bufflen(&g->buff) : newsize;
- + if(newsize < luaZ_sizebuffer(&g->buff))
- + luaZ_resizebuffer(L, &g->buff, newsize);
- }
- }
-
- --- a/src/lstate.c
- +++ b/src/lstate.c
- @@ -118,7 +118,6 @@
-
- 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);
- preinit_state(L1, G(L));
- stack_init(L1, L); /* init stack */
- setobj2n(L, gt(L1), gt(L)); /* share table of globals */
- @@ -126,6 +125,7 @@
- L1->basehookcount = L->basehookcount;
- L1->hook = L->hook;
- resethookcount(L1);
- + luaC_link(L, obj2gco(L1), LUA_TTHREAD);
- lua_assert(iswhite(obj2gco(L1)));
- return L1;
- }
- --- a/src/lstring.c
- +++ b/src/lstring.c
- @@ -53,6 +53,9 @@
- stringtable *tb;
- if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
- 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, (l+1)*sizeof(char)+sizeof(TString)));
- ts->tsv.len = l;
- ts->tsv.hash = h;
- @@ -61,13 +64,10 @@
- ts->tsv.reserved = 0;
- memcpy(ts+1, str, l*sizeof(char));
- ((char *)(ts+1))[l] = '\0'; /* ending 0 */
- - tb = &G(L)->strt;
- h = lmod(h, tb->size);
- ts->tsv.next = tb->hash[h]; /* chain new entry */
- 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;
- }
-
- --- a/src/ltable.c
- +++ b/src/ltable.c
- @@ -371,7 +371,6 @@
-
- Table *luaH_new (lua_State *L, int narray, int nhash) {
- Table *t = luaM_new(L, Table);
- - luaC_link(L, obj2gco(t), LUA_TTABLE);
- t->metatable = NULL;
- t->flags = cast_byte(~0);
- /* temporary values (kept only if some malloc fails) */
- @@ -381,6 +380,7 @@
- t->node = cast(Node *, dummynode);
- setarrayvector(L, t, narray);
- setnodevector(L, t, nhash);
- + luaC_link(L, obj2gco(t), LUA_TTABLE);
- return t;
- }
-
- --- a/src/lvm.c
- +++ b/src/lvm.c
- @@ -375,6 +375,7 @@
- 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 */
- @@ -383,6 +384,7 @@
- tl += l;
- }
- setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
- + luaZ_resetbuffer(&G(L)->buff);
- }
- total -= n-1; /* got `n' strings to create 1 new */
- last -= n-1;
- --- a/src/lua.c
- +++ b/src/lua.c
- @@ -19,6 +19,82 @@
- #include "llimits.h"
-
-
- +typedef struct {
- + char *name;
- + lua_State *L;
- + size_t memused;
- + size_t peak_memused;
- + size_t max_memused;
- + int collecting;
- +} script_info_t;
- +
- +
- +static void *script_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
- +{
- + script_info_t *info=(script_info_t *)ud;
- + size_t old_size = info->memused;
- +
- + info->memused -= osize;
- + if (nsize == 0) {
- + free(ptr);
- + return NULL;
- + }
- + info->memused += nsize;
- + if(info->max_memused > 0 && nsize > osize && info->memused >= info->max_memused) {
- +#ifdef LOW_MEM_DEBUG
- + printf("LOW MEM: 1 osize=%zd, nsize=%zd, used=%zu, peak=%zu, need=%zd\n", osize, nsize,
- + info->memused, info->peak_memused, (info->memused - info->max_memused));
- +#endif
- + info->memused = old_size;
- + /* don't allow a recursive garbage collection call. */
- + if(info->collecting != 0) {
- + return NULL;
- + }
- + info->collecting = 1;
- + /* try to free memory by collecting garbage. */
- + lua_gc(info->L, LUA_GCCOLLECT, 0);
- + info->collecting = 0;
- +#ifdef LOW_MEM_DEBUG
- + printf("LOW MEM: 2 used=%zu, peak=%zu\n", info->memused, info->peak_memused);
- +#endif
- + /* check memory usage again. */
- + old_size = info->memused;
- + info->memused -= osize;
- + info->memused += nsize;
- + if(info->memused >= info->max_memused) {
- + info->memused = old_size;
- +#ifdef LOW_MEM_DEBUG
- + printf("OUT OF MEMORY: memused=%zd, osize=%zd, nsize=%zd\n", info->memused, osize, nsize);
- +#endif
- + return NULL;
- + }
- + }
- + if(info->memused > info->peak_memused) info->peak_memused = info->memused;
- + return realloc(ptr, nsize);
- +}
- +
- +static int set_memory_limit(lua_State *L)
- +{
- + int limit = luaL_checknumber(L, 1);
- + script_info_t *info;
- + lua_getallocf(L, (void *)(&info));
- +
- + if( limit >= 0 )
- + info->max_memused = limit;
- +
- + lua_pushnumber(L, limit);
- + return 1;
- +}
- +
- +static int get_memory_limit(lua_State *L)
- +{
- + script_info_t *info;
- + lua_getallocf(L, (void *)(&info));
- + lua_pushnumber(L, info->max_memused);
- + return 1;
- +}
- +
- +
- static lua_State *globalL = NULL;
-
- static const char *progname = LUA_PROGNAME;
- @@ -377,11 +453,28 @@
- int main (int argc, char **argv) {
- int status;
- struct Smain s;
- - lua_State *L = lua_open(); /* create state */
- + script_info_t *info;
- +
- + info = (script_info_t *)calloc(1, sizeof(script_info_t));
- + info->max_memused = 0;
- + info->collecting = 0;
- + info->name = argv[0];
- + info->memused = 0;
- + info->peak_memused = 0;
- +
- + lua_State *L = lua_newstate(script_alloc, info);
- +
- if (L == NULL) {
- l_message(argv[0], "cannot create state: not enough memory");
- return EXIT_FAILURE;
- }
- +
- + info->L = L;
- +
- + luaL_openlibs(L);
- + lua_register(L, "set_memory_limit", set_memory_limit);
- + lua_register(L, "get_memory_limit", get_memory_limit);
- +
- /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
- */
- #ifdef LNUM_INT16
- @@ -396,6 +489,14 @@
- status = lua_cpcall(L, &pmain, &s);
- report(L, status);
- lua_close(L);
- +
- +#ifdef LOW_MEM_DEBUG
- + printf("%s: memused=%zd, peak_memused=%zd\n", info->name,
- + info->memused, info->peak_memused);
- +#endif
- +
- + free(info);
- +
- return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
- }
-
|