040-memory-limits.patch 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. --- a/src/lapi.c
  2. +++ b/src/lapi.c
  3. @@ -716,14 +716,14 @@
  4. LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
  5. StkId t;
  6. - TValue key;
  7. lua_lock(L);
  8. api_checknelems(L, 1);
  9. t = index2adr(L, idx);
  10. api_checkvalidindex(L, t);
  11. - setsvalue(L, &key, luaS_new(L, k));
  12. - luaV_settable(L, t, &key, L->top - 1);
  13. - L->top--; /* pop value */
  14. + setsvalue2s(L, L->top, luaS_new(L, k));
  15. + api_incr_top(L);
  16. + luaV_settable(L, t, L->top - 1, L->top - 2);
  17. + L->top -= 2; /* pop key and value */
  18. lua_unlock(L);
  19. }
  20. @@ -971,7 +971,12 @@
  21. break;
  22. }
  23. case LUA_GCCOLLECT: {
  24. - luaC_fullgc(L);
  25. + lu_mem old_thres = g->GCthreshold;
  26. + if(g->GCthreshold != MAX_LUMEM) {
  27. + g->GCthreshold = MAX_LUMEM;
  28. + luaC_fullgc(L);
  29. + g->GCthreshold = old_thres;
  30. + }
  31. break;
  32. }
  33. case LUA_GCCOUNT: {
  34. --- a/src/ldo.c
  35. +++ b/src/ldo.c
  36. @@ -494,6 +494,7 @@
  37. struct SParser *p = cast(struct SParser *, ud);
  38. int c = luaZ_lookahead(p->z);
  39. luaC_checkGC(L);
  40. + lua_gc(L, LUA_GCSTOP, 0); /* stop collector during parsing */
  41. tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
  42. &p->buff, p->name);
  43. cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
  44. @@ -502,6 +503,7 @@
  45. cl->l.upvals[i] = luaF_newupval(L);
  46. setclvalue(L, L->top, cl);
  47. incr_top(L);
  48. + lua_gc(L, LUA_GCRESTART, 0);
  49. }
  50. --- a/src/lgc.c
  51. +++ b/src/lgc.c
  52. @@ -437,7 +437,10 @@
  53. /* check size of buffer */
  54. if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
  55. size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
  56. - luaZ_resizebuffer(L, &g->buff, newsize);
  57. + /* make sure newsize is larger then the buffer's in use size. */
  58. + newsize = (luaZ_bufflen(&g->buff) > newsize) ? luaZ_bufflen(&g->buff) : newsize;
  59. + if(newsize < luaZ_sizebuffer(&g->buff))
  60. + luaZ_resizebuffer(L, &g->buff, newsize);
  61. }
  62. }
  63. --- a/src/lstate.c
  64. +++ b/src/lstate.c
  65. @@ -118,7 +118,6 @@
  66. lua_State *luaE_newthread (lua_State *L) {
  67. lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
  68. - luaC_link(L, obj2gco(L1), LUA_TTHREAD);
  69. preinit_state(L1, G(L));
  70. stack_init(L1, L); /* init stack */
  71. setobj2n(L, gt(L1), gt(L)); /* share table of globals */
  72. @@ -126,6 +125,7 @@
  73. L1->basehookcount = L->basehookcount;
  74. L1->hook = L->hook;
  75. resethookcount(L1);
  76. + luaC_link(L, obj2gco(L1), LUA_TTHREAD);
  77. lua_assert(iswhite(obj2gco(L1)));
  78. return L1;
  79. }
  80. --- a/src/lstring.c
  81. +++ b/src/lstring.c
  82. @@ -53,6 +53,9 @@
  83. stringtable *tb;
  84. if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
  85. luaM_toobig(L);
  86. + tb = &G(L)->strt;
  87. + if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
  88. + luaS_resize(L, tb->size*2); /* too crowded */
  89. ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
  90. ts->tsv.len = l;
  91. ts->tsv.hash = h;
  92. @@ -61,13 +64,10 @@
  93. ts->tsv.reserved = 0;
  94. memcpy(ts+1, str, l*sizeof(char));
  95. ((char *)(ts+1))[l] = '\0'; /* ending 0 */
  96. - tb = &G(L)->strt;
  97. h = lmod(h, tb->size);
  98. ts->tsv.next = tb->hash[h]; /* chain new entry */
  99. tb->hash[h] = obj2gco(ts);
  100. tb->nuse++;
  101. - if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
  102. - luaS_resize(L, tb->size*2); /* too crowded */
  103. return ts;
  104. }
  105. --- a/src/ltable.c
  106. +++ b/src/ltable.c
  107. @@ -371,7 +371,6 @@
  108. Table *luaH_new (lua_State *L, int narray, int nhash) {
  109. Table *t = luaM_new(L, Table);
  110. - luaC_link(L, obj2gco(t), LUA_TTABLE);
  111. t->metatable = NULL;
  112. t->flags = cast_byte(~0);
  113. /* temporary values (kept only if some malloc fails) */
  114. @@ -381,6 +380,7 @@
  115. t->node = cast(Node *, dummynode);
  116. setarrayvector(L, t, narray);
  117. setnodevector(L, t, nhash);
  118. + luaC_link(L, obj2gco(t), LUA_TTABLE);
  119. return t;
  120. }
  121. --- a/src/lvm.c
  122. +++ b/src/lvm.c
  123. @@ -375,6 +375,7 @@
  124. if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
  125. tl += l;
  126. }
  127. + G(L)->buff.n = tl;
  128. buffer = luaZ_openspace(L, &G(L)->buff, tl);
  129. tl = 0;
  130. for (i=n; i>0; i--) { /* concat all strings */
  131. @@ -383,6 +384,7 @@
  132. tl += l;
  133. }
  134. setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
  135. + luaZ_resetbuffer(&G(L)->buff);
  136. }
  137. total -= n-1; /* got `n' strings to create 1 new */
  138. last -= n-1;
  139. --- a/src/lua.c
  140. +++ b/src/lua.c
  141. @@ -19,6 +19,82 @@
  142. #include "llimits.h"
  143. +typedef struct {
  144. + char *name;
  145. + lua_State *L;
  146. + size_t memused;
  147. + size_t peak_memused;
  148. + size_t max_memused;
  149. + int collecting;
  150. +} script_info_t;
  151. +
  152. +
  153. +static void *script_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
  154. +{
  155. + script_info_t *info=(script_info_t *)ud;
  156. + size_t old_size = info->memused;
  157. +
  158. + info->memused -= osize;
  159. + if (nsize == 0) {
  160. + free(ptr);
  161. + return NULL;
  162. + }
  163. + info->memused += nsize;
  164. + if(info->max_memused > 0 && nsize > osize && info->memused >= info->max_memused) {
  165. +#ifdef LOW_MEM_DEBUG
  166. + printf("LOW MEM: 1 osize=%zd, nsize=%zd, used=%zu, peak=%zu, need=%zd\n", osize, nsize,
  167. + info->memused, info->peak_memused, (info->memused - info->max_memused));
  168. +#endif
  169. + info->memused = old_size;
  170. + /* don't allow a recursive garbage collection call. */
  171. + if(info->collecting != 0) {
  172. + return NULL;
  173. + }
  174. + info->collecting = 1;
  175. + /* try to free memory by collecting garbage. */
  176. + lua_gc(info->L, LUA_GCCOLLECT, 0);
  177. + info->collecting = 0;
  178. +#ifdef LOW_MEM_DEBUG
  179. + printf("LOW MEM: 2 used=%zu, peak=%zu\n", info->memused, info->peak_memused);
  180. +#endif
  181. + /* check memory usage again. */
  182. + old_size = info->memused;
  183. + info->memused -= osize;
  184. + info->memused += nsize;
  185. + if(info->memused >= info->max_memused) {
  186. + info->memused = old_size;
  187. +#ifdef LOW_MEM_DEBUG
  188. + printf("OUT OF MEMORY: memused=%zd, osize=%zd, nsize=%zd\n", info->memused, osize, nsize);
  189. +#endif
  190. + return NULL;
  191. + }
  192. + }
  193. + if(info->memused > info->peak_memused) info->peak_memused = info->memused;
  194. + return realloc(ptr, nsize);
  195. +}
  196. +
  197. +static int set_memory_limit(lua_State *L)
  198. +{
  199. + int limit = luaL_checknumber(L, 1);
  200. + script_info_t *info;
  201. + lua_getallocf(L, (void *)(&info));
  202. +
  203. + if( limit >= 0 )
  204. + info->max_memused = limit;
  205. +
  206. + lua_pushnumber(L, limit);
  207. + return 1;
  208. +}
  209. +
  210. +static int get_memory_limit(lua_State *L)
  211. +{
  212. + script_info_t *info;
  213. + lua_getallocf(L, (void *)(&info));
  214. + lua_pushnumber(L, info->max_memused);
  215. + return 1;
  216. +}
  217. +
  218. +
  219. static lua_State *globalL = NULL;
  220. static const char *progname = LUA_PROGNAME;
  221. @@ -377,11 +453,28 @@
  222. int main (int argc, char **argv) {
  223. int status;
  224. struct Smain s;
  225. - lua_State *L = lua_open(); /* create state */
  226. + script_info_t *info;
  227. +
  228. + info = (script_info_t *)calloc(1, sizeof(script_info_t));
  229. + info->max_memused = 0;
  230. + info->collecting = 0;
  231. + info->name = argv[0];
  232. + info->memused = 0;
  233. + info->peak_memused = 0;
  234. +
  235. + lua_State *L = lua_newstate(script_alloc, info);
  236. +
  237. if (L == NULL) {
  238. l_message(argv[0], "cannot create state: not enough memory");
  239. return EXIT_FAILURE;
  240. }
  241. +
  242. + info->L = L;
  243. +
  244. + luaL_openlibs(L);
  245. + lua_register(L, "set_memory_limit", set_memory_limit);
  246. + lua_register(L, "get_memory_limit", get_memory_limit);
  247. +
  248. /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
  249. */
  250. #ifdef LNUM_INT16
  251. @@ -396,6 +489,14 @@
  252. status = lua_cpcall(L, &pmain, &s);
  253. report(L, status);
  254. lua_close(L);
  255. +
  256. +#ifdef LOW_MEM_DEBUG
  257. + printf("%s: memused=%zd, peak_memused=%zd\n", info->name,
  258. + info->memused, info->peak_memused);
  259. +#endif
  260. +
  261. + free(info);
  262. +
  263. return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
  264. }