aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c105
-rw-r--r--lauxlib.c48
-rw-r--r--lauxlib.h2
-rw-r--r--lbaselib.c15
-rw-r--r--lcode.c4
-rw-r--r--ldebug.c18
-rw-r--r--ldo.c23
-rw-r--r--ldo.h12
-rw-r--r--ldump.c68
-rw-r--r--lfunc.c8
-rw-r--r--lgc.c416
-rw-r--r--lgc.h58
-rw-r--r--linit.c51
-rw-r--r--llimits.h21
-rw-r--r--lmathlib.c24
-rw-r--r--lmem.c8
-rw-r--r--lmem.h2
-rw-r--r--lobject.h22
-rw-r--r--lparser.c63
-rw-r--r--lstate.c71
-rw-r--r--lstate.h21
-rw-r--r--lstrlib.c1
-rw-r--r--ltable.c80
-rw-r--r--ltable.h14
-rw-r--r--ltablib.c31
-rw-r--r--ltests.c65
-rw-r--r--ltests.h7
-rw-r--r--ltm.c2
-rw-r--r--ltm.h4
-rw-r--r--lua.c6
-rw-r--r--lua.h10
-rw-r--r--lualib.h39
-rw-r--r--lundump.c87
-rw-r--r--lundump.h5
-rw-r--r--lvm.c107
-rw-r--r--lzio.c36
-rw-r--r--lzio.h1
-rw-r--r--manual/manual.of179
-rw-r--r--testes/all.lua2
-rw-r--r--testes/api.lua65
-rw-r--r--testes/attrib.lua2
-rw-r--r--testes/calls.lua27
-rw-r--r--testes/closure.lua19
-rw-r--r--testes/coroutine.lua2
-rw-r--r--testes/files.lua4
-rw-r--r--testes/main.lua6
-rw-r--r--testes/nextvar.lua14
47 files changed, 1024 insertions, 851 deletions
diff --git a/lapi.c b/lapi.c
index 76c9d31b..34b335fd 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1101,16 +1101,37 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
1101} 1101}
1102 1102
1103 1103
1104/*
1105** Dump a function, calling 'writer' to write its parts. Because the
1106** writer can use the stack in unkown ways, this function should not
1107** push things on the stack, but it must anchor an auxiliary table
1108** used by 'luaU_dump'. To do so, it creates the table, anchors the
1109** function that is on the stack in the table, and substitutes the
1110** table for the function in the stack.
1111*/
1112
1104LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { 1113LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
1105 int status; 1114 int status;
1115 StkId fstk; /* pointer to function */
1106 TValue *o; 1116 TValue *o;
1107 lua_lock(L); 1117 lua_lock(L);
1108 api_checknelems(L, 1); 1118 api_checknelems(L, 1);
1109 o = s2v(L->top.p - 1); 1119 fstk = L->top.p - 1;
1110 if (isLfunction(o)) 1120 o = s2v(fstk);
1111 status = luaU_dump(L, getproto(o), writer, data, strip); 1121 if (!isLfunction(o))
1112 else
1113 status = 1; 1122 status = 1;
1123 else {
1124 LClosure *f = clLvalue(o);
1125 ptrdiff_t fidx = savestack(L, fstk); /* function index */
1126 Table *h = luaH_new(L); /* auxiliary table used by 'luaU_dump' */
1127 sethvalue2s(L, L->top.p, h); /* anchor it (luaH_set may call GC) */
1128 L->top.p++; /* (assume extra slot) */
1129 luaH_set(L, h, o, o); /* anchor function into table */
1130 setobjs2s(L, fstk, L->top.p - 1); /* move table over function */
1131 L->top.p--; /* stack back to initial size */
1132 status = luaU_dump(L, f->p, writer, data, strip, h);
1133 setclLvalue2s(L, restorestack(L, fidx), f); /* put function back */
1134 }
1114 lua_unlock(L); 1135 lua_unlock(L);
1115 return status; 1136 return status;
1116} 1137}
@@ -1139,7 +1160,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1139 } 1160 }
1140 case LUA_GCRESTART: { 1161 case LUA_GCRESTART: {
1141 luaE_setdebt(g, 0); 1162 luaE_setdebt(g, 0);
1142 g->gcstp = 0; /* (GCSTPGC must be already zero here) */ 1163 g->gcstp = 0; /* (bit GCSTPGC must be zero here) */
1143 break; 1164 break;
1144 } 1165 }
1145 case LUA_GCCOLLECT: { 1166 case LUA_GCCOLLECT: {
@@ -1148,42 +1169,46 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1148 } 1169 }
1149 case LUA_GCCOUNT: { 1170 case LUA_GCCOUNT: {
1150 /* GC values are expressed in Kbytes: #bytes/2^10 */ 1171 /* GC values are expressed in Kbytes: #bytes/2^10 */
1151 res = cast_int(gettotalbytes(g) >> 10); 1172 res = cast_int(g->totalbytes >> 10);
1152 break; 1173 break;
1153 } 1174 }
1154 case LUA_GCCOUNTB: { 1175 case LUA_GCCOUNTB: {
1155 res = cast_int(gettotalbytes(g) & 0x3ff); 1176 res = cast_int(g->totalbytes & 0x3ff);
1156 break; 1177 break;
1157 } 1178 }
1158 case LUA_GCSTEP: { 1179 case LUA_GCSTEP: {
1159 int data = va_arg(argp, int); 1180 int todo = va_arg(argp, int); /* work to be done */
1160 l_mem debt = 1; /* =1 to signal that it did an actual step */ 1181 int didsomething = 0;
1161 lu_byte oldstp = g->gcstp; 1182 lu_byte oldstp = g->gcstp;
1162 g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */ 1183 g->gcstp = 0; /* allow GC to run (bit GCSTPGC must be zero here) */
1163 if (data == 0) { 1184 if (todo == 0)
1164 luaE_setdebt(g, 0); /* do a basic step */ 1185 todo = 1 << g->gcstepsize; /* standard step size */
1165 luaC_step(L); 1186 while (todo >= g->GCdebt) { /* enough to run a step? */
1166 } 1187 todo -= g->GCdebt; /* decrement 'todo' */
1167 else { /* add 'data' to total debt */ 1188 luaC_step(L); /* run one basic step */
1168 debt = cast(l_mem, data) * 1024 + g->GCdebt; 1189 didsomething = 1;
1169 luaE_setdebt(g, debt); 1190 if (g->gckind == KGC_GEN) /* minor collections? */
1170 luaC_checkGC(L); 1191 todo = 0; /* doesn't make sense to repeat in this case */
1192 else if (g->gcstate == GCSpause)
1193 break; /* don't run more than one cycle */
1171 } 1194 }
1195 /* remove remaining 'todo' from total debt */
1196 luaE_setdebt(g, g->GCdebt - todo);
1172 g->gcstp = oldstp; /* restore previous state */ 1197 g->gcstp = oldstp; /* restore previous state */
1173 if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ 1198 if (didsomething && g->gcstate == GCSpause) /* end of cycle? */
1174 res = 1; /* signal it */ 1199 res = 1; /* signal it */
1175 break; 1200 break;
1176 } 1201 }
1177 case LUA_GCSETPAUSE: { 1202 case LUA_GCSETPAUSE: {
1178 int data = va_arg(argp, int); 1203 unsigned int data = va_arg(argp, unsigned int);
1179 res = getgcparam(g->gcpause); 1204 res = applygcparam(g, gcpause, 100);
1180 setgcparam(g->gcpause, data); 1205 setgcparam(g, gcpause, data);
1181 break; 1206 break;
1182 } 1207 }
1183 case LUA_GCSETSTEPMUL: { 1208 case LUA_GCSETSTEPMUL: {
1184 int data = va_arg(argp, int); 1209 unsigned int data = va_arg(argp, unsigned int);
1185 res = getgcparam(g->gcstepmul); 1210 res = applygcparam(g, gcstepmul, 100);
1186 setgcparam(g->gcstepmul, data); 1211 setgcparam(g, gcstepmul, data);
1187 break; 1212 break;
1188 } 1213 }
1189 case LUA_GCISRUNNING: { 1214 case LUA_GCISRUNNING: {
@@ -1191,27 +1216,28 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1191 break; 1216 break;
1192 } 1217 }
1193 case LUA_GCGEN: { 1218 case LUA_GCGEN: {
1194 int minormul = va_arg(argp, int); 1219 unsigned int minormul = va_arg(argp, unsigned int);
1195 int majormul = va_arg(argp, int); 1220 unsigned int majormul = va_arg(argp, unsigned int);
1196 res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1221 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1197 if (minormul != 0) 1222 if (minormul != 0)
1198 g->genminormul = minormul; 1223 setgcparam(g, genminormul, minormul);
1199 if (majormul != 0) 1224 if (majormul != 0)
1200 setgcparam(g->genmajormul, majormul); 1225 setgcparam(g, genmajormul, majormul);
1201 luaC_changemode(L, KGC_GEN); 1226 luaC_changemode(L, KGC_GEN);
1202 break; 1227 break;
1203 } 1228 }
1204 case LUA_GCINC: { 1229 case LUA_GCINC: {
1205 int pause = va_arg(argp, int); 1230 unsigned int pause = va_arg(argp, unsigned int);
1206 int stepmul = va_arg(argp, int); 1231 unsigned int stepmul = va_arg(argp, unsigned int);
1207 int stepsize = va_arg(argp, int); 1232 unsigned int stepsize = va_arg(argp, unsigned int);
1208 res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1233 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1209 if (pause != 0) 1234 if (pause != 0)
1210 setgcparam(g->gcpause, pause); 1235 setgcparam(g, gcpause, pause);
1211 if (stepmul != 0) 1236 if (stepmul != 0)
1212 setgcparam(g->gcstepmul, stepmul); 1237 setgcparam(g, gcstepmul, stepmul);
1213 if (stepsize != 0) 1238 if (stepsize != 0)
1214 g->gcstepsize = stepsize; 1239 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
1240 : log2maxs(l_obj);
1215 luaC_changemode(L, KGC_INC); 1241 luaC_changemode(L, KGC_INC);
1216 break; 1242 break;
1217 } 1243 }
@@ -1279,13 +1305,14 @@ LUA_API void lua_toclose (lua_State *L, int idx) {
1279LUA_API void lua_concat (lua_State *L, int n) { 1305LUA_API void lua_concat (lua_State *L, int n) {
1280 lua_lock(L); 1306 lua_lock(L);
1281 api_checknelems(L, n); 1307 api_checknelems(L, n);
1282 if (n > 0) 1308 if (n > 0) {
1283 luaV_concat(L, n); 1309 luaV_concat(L, n);
1310 luaC_checkGC(L);
1311 }
1284 else { /* nothing to concatenate */ 1312 else { /* nothing to concatenate */
1285 setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ 1313 setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */
1286 api_incr_top(L); 1314 api_incr_top(L);
1287 } 1315 }
1288 luaC_checkGC(L);
1289 lua_unlock(L); 1316 lua_unlock(L);
1290} 1317}
1291 1318
diff --git a/lauxlib.c b/lauxlib.c
index 4ca6c654..555a5976 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1091,8 +1091,54 @@ static void warnfon (void *ud, const char *message, int tocont) {
1091} 1091}
1092 1092
1093 1093
1094
1095/*
1096** A function to compute an unsigned int with some level of
1097** randomness. Rely on Address Space Layout Randomization (if present)
1098** and the current time.
1099*/
1100#if !defined(luai_makeseed)
1101
1102#include <time.h>
1103
1104
1105/*
1106** Size of 'e' measured in number of 'unsigned int's. (In the weird
1107** case that the division truncates, we just lose some part of the
1108** value, no big deal.)
1109*/
1110#define sof(e) (sizeof(e) / sizeof(unsigned int))
1111
1112
1113#define addbuff(b,v) \
1114 (memcpy(b, &(v), sof(v) * sizeof(unsigned int)), b += sof(v))
1115
1116
1117static unsigned int luai_makeseed (void) {
1118 unsigned int buff[sof(void*) + sof(time_t)];
1119 unsigned int res;
1120 unsigned int *b = buff;
1121 time_t t = time(NULL);
1122 void *h = buff;
1123 addbuff(b, h); /* local variable's address */
1124 addbuff(b, t); /* time */
1125 res = buff[0];
1126 for (b = buff + 1; b < buff + sof(buff); b++)
1127 res ^= (res >> 3) + (res << 7) + *b;
1128 return res;
1129}
1130
1131#endif
1132
1133
1134LUALIB_API unsigned int luaL_makeseed (lua_State *L) {
1135 (void)L; /* unused */
1136 return luai_makeseed();
1137}
1138
1139
1094LUALIB_API lua_State *luaL_newstate (void) { 1140LUALIB_API lua_State *luaL_newstate (void) {
1095 lua_State *L = lua_newstate(l_alloc, NULL); 1141 lua_State *L = lua_newstate(l_alloc, NULL, luai_makeseed());
1096 if (l_likely(L)) { 1142 if (l_likely(L)) {
1097 lua_atpanic(L, &panic); 1143 lua_atpanic(L, &panic);
1098 lua_setwarnf(L, warnfoff, L); /* default is warnings off */ 1144 lua_setwarnf(L, warnfoff, L); /* default is warnings off */
diff --git a/lauxlib.h b/lauxlib.h
index 5b977e2a..0ee9a572 100644
--- a/lauxlib.h
+++ b/lauxlib.h
@@ -100,6 +100,8 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
100 100
101LUALIB_API lua_State *(luaL_newstate) (void); 101LUALIB_API lua_State *(luaL_newstate) (void);
102 102
103LUALIB_API unsigned int luaL_makeseed (lua_State *L);
104
103LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); 105LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
104 106
105LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s, 107LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
diff --git a/lbaselib.c b/lbaselib.c
index 1d60c9de..5a23c937 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -337,9 +337,20 @@ static int load_aux (lua_State *L, int status, int envidx) {
337} 337}
338 338
339 339
340static const char *getmode (lua_State *L, int idx) {
341 const char *mode = luaL_optstring(L, idx, "bt");
342 int i = 0;
343 if (mode[i] == 'b') i++;
344 if (mode[i] == 't') i++;
345 if (mode[i] != '\0')
346 luaL_argerror(L, idx, "invalid mode");
347 return mode;
348}
349
350
340static int luaB_loadfile (lua_State *L) { 351static int luaB_loadfile (lua_State *L) {
341 const char *fname = luaL_optstring(L, 1, NULL); 352 const char *fname = luaL_optstring(L, 1, NULL);
342 const char *mode = luaL_optstring(L, 2, NULL); 353 const char *mode = getmode(L, 2);
343 int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ 354 int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
344 int status = luaL_loadfilex(L, fname, mode); 355 int status = luaL_loadfilex(L, fname, mode);
345 return load_aux(L, status, env); 356 return load_aux(L, status, env);
@@ -388,7 +399,7 @@ static int luaB_load (lua_State *L) {
388 int status; 399 int status;
389 size_t l; 400 size_t l;
390 const char *s = lua_tolstring(L, 1, &l); 401 const char *s = lua_tolstring(L, 1, &l);
391 const char *mode = luaL_optstring(L, 3, "bt"); 402 const char *mode = getmode(L, 3);
392 int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ 403 int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
393 if (s != NULL) { /* loading a string? */ 404 if (s != NULL) { /* loading a string? */
394 const char *chunkname = luaL_optstring(L, 2, s); 405 const char *chunkname = luaL_optstring(L, 2, s);
diff --git a/lcode.c b/lcode.c
index 29db5002..0d888822 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1849,7 +1849,7 @@ void luaK_finish (FuncState *fs) {
1849 lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); 1849 lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc));
1850 switch (GET_OPCODE(*pc)) { 1850 switch (GET_OPCODE(*pc)) {
1851 case OP_RETURN0: case OP_RETURN1: { 1851 case OP_RETURN0: case OP_RETURN1: {
1852 if (!(fs->needclose || p->is_vararg)) 1852 if (!(fs->needclose || (p->flag & PF_ISVARARG)))
1853 break; /* no extra work */ 1853 break; /* no extra work */
1854 /* else use OP_RETURN to do the extra work */ 1854 /* else use OP_RETURN to do the extra work */
1855 SET_OPCODE(*pc, OP_RETURN); 1855 SET_OPCODE(*pc, OP_RETURN);
@@ -1857,7 +1857,7 @@ void luaK_finish (FuncState *fs) {
1857 case OP_RETURN: case OP_TAILCALL: { 1857 case OP_RETURN: case OP_TAILCALL: {
1858 if (fs->needclose) 1858 if (fs->needclose)
1859 SETARG_k(*pc, 1); /* signal that it needs to close */ 1859 SETARG_k(*pc, 1); /* signal that it needs to close */
1860 if (p->is_vararg) 1860 if (p->flag & PF_ISVARARG)
1861 SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ 1861 SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */
1862 break; 1862 break;
1863 } 1863 }
diff --git a/ldebug.c b/ldebug.c
index b1f16ac9..8b4bd546 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -182,7 +182,7 @@ static const char *upvalname (const Proto *p, int uv) {
182 182
183 183
184static const char *findvararg (CallInfo *ci, int n, StkId *pos) { 184static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
185 if (clLvalue(s2v(ci->func.p))->p->is_vararg) { 185 if (clLvalue(s2v(ci->func.p))->p->flag & PF_ISVARARG) {
186 int nextra = ci->u.l.nextraargs; 186 int nextra = ci->u.l.nextraargs;
187 if (n >= -nextra) { /* 'n' is negative */ 187 if (n >= -nextra) { /* 'n' is negative */
188 *pos = ci->func.p - nextra - (n + 1); 188 *pos = ci->func.p - nextra - (n + 1);
@@ -264,8 +264,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) {
264 else { 264 else {
265 const Proto *p = cl->l.p; 265 const Proto *p = cl->l.p;
266 if (p->source) { 266 if (p->source) {
267 ar->source = getstr(p->source); 267 ar->source = getlstr(p->source, ar->srclen);
268 ar->srclen = tsslen(p->source);
269 } 268 }
270 else { 269 else {
271 ar->source = "=?"; 270 ar->source = "=?";
@@ -301,7 +300,7 @@ static void collectvalidlines (lua_State *L, Closure *f) {
301 sethvalue2s(L, L->top.p, t); /* push it on stack */ 300 sethvalue2s(L, L->top.p, t); /* push it on stack */
302 api_incr_top(L); 301 api_incr_top(L);
303 setbtvalue(&v); /* boolean 'true' to be the value of all indices */ 302 setbtvalue(&v); /* boolean 'true' to be the value of all indices */
304 if (!p->is_vararg) /* regular function? */ 303 if (!(p->flag & PF_ISVARARG)) /* regular function? */
305 i = 0; /* consider all instructions */ 304 i = 0; /* consider all instructions */
306 else { /* vararg function */ 305 else { /* vararg function */
307 lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); 306 lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
@@ -344,7 +343,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
344 ar->nparams = 0; 343 ar->nparams = 0;
345 } 344 }
346 else { 345 else {
347 ar->isvararg = f->l.p->is_vararg; 346 ar->isvararg = f->l.p->flag & PF_ISVARARG;
348 ar->nparams = f->l.p->numparams; 347 ar->nparams = f->l.p->numparams;
349 } 348 }
350 break; 349 break;
@@ -812,8 +811,11 @@ l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
812const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, 811const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
813 int line) { 812 int line) {
814 char buff[LUA_IDSIZE]; 813 char buff[LUA_IDSIZE];
815 if (src) 814 if (src) {
816 luaO_chunkid(buff, getstr(src), tsslen(src)); 815 size_t idlen;
816 const char *id = getlstr(src, idlen);
817 luaO_chunkid(buff, id, idlen);
818 }
817 else { /* no source available; use "?" instead */ 819 else { /* no source available; use "?" instead */
818 buff[0] = '?'; buff[1] = '\0'; 820 buff[0] = '?'; buff[1] = '\0';
819 } 821 }
@@ -893,7 +895,7 @@ int luaG_tracecall (lua_State *L) {
893 Proto *p = ci_func(ci)->p; 895 Proto *p = ci_func(ci)->p;
894 ci->u.l.trap = 1; /* ensure hooks will be checked */ 896 ci->u.l.trap = 1; /* ensure hooks will be checked */
895 if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */ 897 if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */
896 if (p->is_vararg) 898 if (p->flag & PF_ISVARARG)
897 return 0; /* hooks will start at VARARGPREP instruction */ 899 return 0; /* hooks will start at VARARGPREP instruction */
898 else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yieded? */ 900 else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yieded? */
899 luaD_hookcall(L, ci); /* check 'call' hook */ 901 luaD_hookcall(L, ci); /* check 'call' hook */
diff --git a/ldo.c b/ldo.c
index bd8d965f..e9f91384 100644
--- a/ldo.c
+++ b/ldo.c
@@ -391,7 +391,7 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
391 int ftransfer; 391 int ftransfer;
392 if (isLua(ci)) { 392 if (isLua(ci)) {
393 Proto *p = ci_func(ci)->p; 393 Proto *p = ci_func(ci)->p;
394 if (p->is_vararg) 394 if (p->flag & PF_ISVARARG)
395 delta = ci->u.l.nextraargs + p->numparams + 1; 395 delta = ci->u.l.nextraargs + p->numparams + 1;
396 } 396 }
397 ci->func.p += delta; /* if vararg, back to virtual 'func' */ 397 ci->func.p += delta; /* if vararg, back to virtual 'func' */
@@ -412,7 +412,7 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
412static StkId tryfuncTM (lua_State *L, StkId func) { 412static StkId tryfuncTM (lua_State *L, StkId func) {
413 const TValue *tm; 413 const TValue *tm;
414 StkId p; 414 StkId p;
415 checkstackGCp(L, 1, func); /* space for metamethod */ 415 checkstackp(L, 1, func); /* space for metamethod */
416 tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ 416 tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */
417 if (l_unlikely(ttisnil(tm))) 417 if (l_unlikely(ttisnil(tm)))
418 luaG_callerror(L, s2v(func)); /* nothing to call */ 418 luaG_callerror(L, s2v(func)); /* nothing to call */
@@ -517,7 +517,7 @@ l_sinline int precallC (lua_State *L, StkId func, int nresults,
517 lua_CFunction f) { 517 lua_CFunction f) {
518 int n; /* number of returns */ 518 int n; /* number of returns */
519 CallInfo *ci; 519 CallInfo *ci;
520 checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ 520 checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
521 L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, 521 L->ci = ci = prepCallInfo(L, func, nresults, CIST_C,
522 L->top.p + LUA_MINSTACK); 522 L->top.p + LUA_MINSTACK);
523 lua_assert(ci->top.p <= L->stack_last.p); 523 lua_assert(ci->top.p <= L->stack_last.p);
@@ -553,7 +553,7 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
553 int fsize = p->maxstacksize; /* frame size */ 553 int fsize = p->maxstacksize; /* frame size */
554 int nfixparams = p->numparams; 554 int nfixparams = p->numparams;
555 int i; 555 int i;
556 checkstackGCp(L, fsize - delta, func); 556 checkstackp(L, fsize - delta, func);
557 ci->func.p -= delta; /* restore 'func' (if vararg) */ 557 ci->func.p -= delta; /* restore 'func' (if vararg) */
558 for (i = 0; i < narg1; i++) /* move down function and arguments */ 558 for (i = 0; i < narg1; i++) /* move down function and arguments */
559 setobjs2s(L, ci->func.p + i, func + i); 559 setobjs2s(L, ci->func.p + i, func + i);
@@ -600,7 +600,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
600 int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */ 600 int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */
601 int nfixparams = p->numparams; 601 int nfixparams = p->numparams;
602 int fsize = p->maxstacksize; /* frame size */ 602 int fsize = p->maxstacksize; /* frame size */
603 checkstackGCp(L, fsize, func); 603 checkstackp(L, fsize, func);
604 L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); 604 L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize);
605 ci->u.l.savedpc = p->code; /* starting point */ 605 ci->u.l.savedpc = p->code; /* starting point */
606 for (; narg < nfixparams; narg++) 606 for (; narg < nfixparams; narg++)
@@ -977,7 +977,7 @@ struct SParser { /* data to 'f_parser' */
977 977
978 978
979static void checkmode (lua_State *L, const char *mode, const char *x) { 979static void checkmode (lua_State *L, const char *mode, const char *x) {
980 if (mode && strchr(mode, x[0]) == NULL) { 980 if (strchr(mode, x[0]) == NULL) {
981 luaO_pushfstring(L, 981 luaO_pushfstring(L,
982 "attempt to load a %s chunk (mode is '%s')", x, mode); 982 "attempt to load a %s chunk (mode is '%s')", x, mode);
983 luaD_throw(L, LUA_ERRSYNTAX); 983 luaD_throw(L, LUA_ERRSYNTAX);
@@ -988,13 +988,18 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
988static void f_parser (lua_State *L, void *ud) { 988static void f_parser (lua_State *L, void *ud) {
989 LClosure *cl; 989 LClosure *cl;
990 struct SParser *p = cast(struct SParser *, ud); 990 struct SParser *p = cast(struct SParser *, ud);
991 const char *mode = p->mode ? p->mode : "bt";
991 int c = zgetc(p->z); /* read first character */ 992 int c = zgetc(p->z); /* read first character */
992 if (c == LUA_SIGNATURE[0]) { 993 if (c == LUA_SIGNATURE[0]) {
993 checkmode(L, p->mode, "binary"); 994 int fixed = 0;
994 cl = luaU_undump(L, p->z, p->name); 995 if (strchr(mode, 'B') != NULL)
996 fixed = 1;
997 else
998 checkmode(L, mode, "binary");
999 cl = luaU_undump(L, p->z, p->name, fixed);
995 } 1000 }
996 else { 1001 else {
997 checkmode(L, p->mode, "text"); 1002 checkmode(L, mode, "text");
998 cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); 1003 cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
999 } 1004 }
1000 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 1005 lua_assert(cl->nupvalues == cl->p->sizeupvalues);
diff --git a/ldo.h b/ldo.h
index 56008ab3..4bc75030 100644
--- a/ldo.h
+++ b/ldo.h
@@ -44,18 +44,6 @@
44 p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ 44 p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
45 45
46 46
47/* macro to check stack size and GC, preserving 'p' */
48#define checkstackGCp(L,n,p) \
49 luaD_checkstackaux(L, n, \
50 ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
51 luaC_checkGC(L), /* stack grow uses memory */ \
52 p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
53
54
55/* macro to check stack size and GC */
56#define checkstackGC(L,fsize) \
57 luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
58
59 47
60/* type of protected functions, to be ran by 'runprotected' */ 48/* type of protected functions, to be ran by 'runprotected' */
61typedef void (*Pfunc) (lua_State *L, void *ud); 49typedef void (*Pfunc) (lua_State *L, void *ud);
diff --git a/ldump.c b/ldump.c
index f231691b..01169c12 100644
--- a/ldump.c
+++ b/ldump.c
@@ -15,8 +15,10 @@
15 15
16#include "lua.h" 16#include "lua.h"
17 17
18#include "lgc.h"
18#include "lobject.h" 19#include "lobject.h"
19#include "lstate.h" 20#include "lstate.h"
21#include "ltable.h"
20#include "lundump.h" 22#include "lundump.h"
21 23
22 24
@@ -24,8 +26,11 @@ typedef struct {
24 lua_State *L; 26 lua_State *L;
25 lua_Writer writer; 27 lua_Writer writer;
26 void *data; 28 void *data;
29 lu_mem offset; /* current position relative to beginning of dump */
27 int strip; 30 int strip;
28 int status; 31 int status;
32 Table *h; /* table to track saved strings */
33 lua_Integer nstr; /* counter to number saved strings */
29} DumpState; 34} DumpState;
30 35
31 36
@@ -43,6 +48,17 @@ static void dumpBlock (DumpState *D, const void *b, size_t size) {
43 lua_unlock(D->L); 48 lua_unlock(D->L);
44 D->status = (*D->writer)(D->L, b, size, D->data); 49 D->status = (*D->writer)(D->L, b, size, D->data);
45 lua_lock(D->L); 50 lua_lock(D->L);
51 D->offset += size;
52 }
53}
54
55
56static void dumpAlign (DumpState *D, int align) {
57 int padding = align - (D->offset % align);
58 if (padding < align) { /* apd == align means no padding */
59 static lua_Integer paddingContent = 0;
60 dumpBlock(D, &paddingContent, padding);
61 lua_assert(D->offset % align == 0);
46 } 62 }
47} 63}
48 64
@@ -89,25 +105,46 @@ static void dumpInteger (DumpState *D, lua_Integer x) {
89} 105}
90 106
91 107
92static void dumpString (DumpState *D, const TString *s) { 108/*
93 if (s == NULL) 109** Dump a String. First dump its "size": size==0 means NULL;
110** size==1 is followed by an index and means "reuse saved string with
111** that index"; size>=2 is followed by the string contents with real
112** size==size-2 and means that string, which will be saved with
113** the next available index.
114*/
115static void dumpString (DumpState *D, TString *ts) {
116 if (ts == NULL)
94 dumpSize(D, 0); 117 dumpSize(D, 0);
95 else { 118 else {
96 size_t size = tsslen(s); 119 const TValue *idx = luaH_getstr(D->h, ts);
97 const char *str = getstr(s); 120 if (ttisinteger(idx)) { /* string already saved? */
98 dumpSize(D, size + 1); 121 dumpSize(D, 1); /* reuse a saved string */
99 dumpVector(D, str, size); 122 dumpInt(D, ivalue(idx)); /* index of saved string */
123 }
124 else { /* must write and save the string */
125 TValue key, value; /* to save the string in the hash */
126 size_t size;
127 const char *s = getlstr(ts, size);
128 dumpSize(D, size + 2);
129 dumpVector(D, s, size);
130 D->nstr++; /* one more saved string */
131 setsvalue(D->L, &key, ts); /* the string is the key */
132 setivalue(&value, D->nstr); /* its index is the value */
133 luaH_finishset(D->L, D->h, &key, idx, &value); /* h[ts] = nstr */
134 /* integer value does not need barrier */
135 }
100 } 136 }
101} 137}
102 138
103 139
104static void dumpCode (DumpState *D, const Proto *f) { 140static void dumpCode (DumpState *D, const Proto *f) {
105 dumpInt(D, f->sizecode); 141 dumpInt(D, f->sizecode);
142 dumpAlign(D, sizeof(f->code[0]));
106 dumpVector(D, f->code, f->sizecode); 143 dumpVector(D, f->code, f->sizecode);
107} 144}
108 145
109 146
110static void dumpFunction(DumpState *D, const Proto *f, TString *psource); 147static void dumpFunction(DumpState *D, const Proto *f);
111 148
112static void dumpConstants (DumpState *D, const Proto *f) { 149static void dumpConstants (DumpState *D, const Proto *f) {
113 int i; 150 int i;
@@ -140,7 +177,7 @@ static void dumpProtos (DumpState *D, const Proto *f) {
140 int n = f->sizep; 177 int n = f->sizep;
141 dumpInt(D, n); 178 dumpInt(D, n);
142 for (i = 0; i < n; i++) 179 for (i = 0; i < n; i++)
143 dumpFunction(D, f->p[i], f->source); 180 dumpFunction(D, f->p[i]);
144} 181}
145 182
146 183
@@ -180,15 +217,15 @@ static void dumpDebug (DumpState *D, const Proto *f) {
180} 217}
181 218
182 219
183static void dumpFunction (DumpState *D, const Proto *f, TString *psource) { 220static void dumpFunction (DumpState *D, const Proto *f) {
184 if (D->strip || f->source == psource) 221 if (D->strip)
185 dumpString(D, NULL); /* no debug info or same source as its parent */ 222 dumpString(D, NULL); /* no debug info */
186 else 223 else
187 dumpString(D, f->source); 224 dumpString(D, f->source);
188 dumpInt(D, f->linedefined); 225 dumpInt(D, f->linedefined);
189 dumpInt(D, f->lastlinedefined); 226 dumpInt(D, f->lastlinedefined);
190 dumpByte(D, f->numparams); 227 dumpByte(D, f->numparams);
191 dumpByte(D, f->is_vararg); 228 dumpByte(D, f->flag);
192 dumpByte(D, f->maxstacksize); 229 dumpByte(D, f->maxstacksize);
193 dumpCode(D, f); 230 dumpCode(D, f);
194 dumpConstants(D, f); 231 dumpConstants(D, f);
@@ -215,16 +252,19 @@ static void dumpHeader (DumpState *D) {
215** dump Lua function as precompiled chunk 252** dump Lua function as precompiled chunk
216*/ 253*/
217int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 254int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
218 int strip) { 255 int strip, Table *h) {
219 DumpState D; 256 DumpState D;
220 D.L = L; 257 D.L = L;
221 D.writer = w; 258 D.writer = w;
259 D.offset = 0;
222 D.data = data; 260 D.data = data;
223 D.strip = strip; 261 D.strip = strip;
224 D.status = 0; 262 D.status = 0;
263 D.h = h;
264 D.nstr = 0;
225 dumpHeader(&D); 265 dumpHeader(&D);
226 dumpByte(&D, f->sizeupvalues); 266 dumpByte(&D, f->sizeupvalues);
227 dumpFunction(&D, f, NULL); 267 dumpFunction(&D, f);
228 return D.status; 268 return D.status;
229} 269}
230 270
diff --git a/lfunc.c b/lfunc.c
index 0945f241..066409c0 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -253,7 +253,7 @@ Proto *luaF_newproto (lua_State *L) {
253 f->upvalues = NULL; 253 f->upvalues = NULL;
254 f->sizeupvalues = 0; 254 f->sizeupvalues = 0;
255 f->numparams = 0; 255 f->numparams = 0;
256 f->is_vararg = 0; 256 f->flag = 0;
257 f->maxstacksize = 0; 257 f->maxstacksize = 0;
258 f->locvars = NULL; 258 f->locvars = NULL;
259 f->sizelocvars = 0; 259 f->sizelocvars = 0;
@@ -265,10 +265,12 @@ Proto *luaF_newproto (lua_State *L) {
265 265
266 266
267void luaF_freeproto (lua_State *L, Proto *f) { 267void luaF_freeproto (lua_State *L, Proto *f) {
268 luaM_freearray(L, f->code, f->sizecode); 268 if (!(f->flag & PF_FIXED)) {
269 luaM_freearray(L, f->code, f->sizecode);
270 luaM_freearray(L, f->lineinfo, f->sizelineinfo);
271 }
269 luaM_freearray(L, f->p, f->sizep); 272 luaM_freearray(L, f->p, f->sizep);
270 luaM_freearray(L, f->k, f->sizek); 273 luaM_freearray(L, f->k, f->sizek);
271 luaM_freearray(L, f->lineinfo, f->sizelineinfo);
272 luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo); 274 luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo);
273 luaM_freearray(L, f->locvars, f->sizelocvars); 275 luaM_freearray(L, f->locvars, f->sizelocvars);
274 luaM_freearray(L, f->upvalues, f->sizeupvalues); 276 luaM_freearray(L, f->upvalues, f->sizeupvalues);
diff --git a/lgc.c b/lgc.c
index f291cd17..e4f8e396 100644
--- a/lgc.c
+++ b/lgc.c
@@ -9,7 +9,6 @@
9 9
10#include "lprefix.h" 10#include "lprefix.h"
11 11
12#include <stdio.h>
13#include <string.h> 12#include <string.h>
14 13
15 14
@@ -19,6 +18,7 @@
19#include "ldo.h" 18#include "ldo.h"
20#include "lfunc.h" 19#include "lfunc.h"
21#include "lgc.h" 20#include "lgc.h"
21#include "llex.h"
22#include "lmem.h" 22#include "lmem.h"
23#include "lobject.h" 23#include "lobject.h"
24#include "lstate.h" 24#include "lstate.h"
@@ -28,36 +28,18 @@
28 28
29 29
30/* 30/*
31** Maximum number of elements to sweep in each single step. 31** Number of fixed (luaC_fix) objects in a Lua state: metafield names,
32** (Large enough to dissipate fixed overheads but small enough 32** plus reserved words, plus "_ENV", plus the memory-error message.
33** to allow small steps for the collector.)
34*/
35#define GCSWEEPMAX 100
36
37/*
38** Maximum number of finalizers to call in each single step.
39*/
40#define GCFINMAX 10
41
42
43/*
44** Cost of calling one finalizer.
45*/
46#define GCFINALIZECOST 50
47
48
49/*
50** The equivalent, in bytes, of one unit of "work" (visiting a slot,
51** sweeping an object, etc.)
52*/ 33*/
53#define WORK2MEM sizeof(TValue) 34#define NFIXED (TM_N + NUM_RESERVED + 2)
54 35
55 36
56/* 37/*
57** macro to adjust 'pause': 'pause' is actually used like 38** Maximum number of elements to sweep in each single step.
58** 'pause / PAUSEADJ' (value chosen by tests) 39** (Large enough to dissipate fixed overheads but small enough
40** to allow small steps for the collector.)
59*/ 41*/
60#define PAUSEADJ 100 42#define GCSWEEPMAX 20
61 43
62 44
63/* mask with all color bits */ 45/* mask with all color bits */
@@ -112,7 +94,7 @@
112#define markobjectN(g,t) { if (t) markobject(g,t); } 94#define markobjectN(g,t) { if (t) markobject(g,t); }
113 95
114static void reallymarkobject (global_State *g, GCObject *o); 96static void reallymarkobject (global_State *g, GCObject *o);
115static lu_mem atomic (lua_State *L); 97static l_obj atomic (lua_State *L);
116static void entersweep (lua_State *L); 98static void entersweep (lua_State *L);
117 99
118 100
@@ -224,7 +206,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
224 } 206 }
225 else { /* sweep phase */ 207 else { /* sweep phase */
226 lua_assert(issweepphase(g)); 208 lua_assert(issweepphase(g));
227 if (g->gckind == KGC_INC) /* incremental mode? */ 209 if (g->gckind != KGC_GEN) /* incremental mode? */
228 makewhite(g, o); /* mark 'o' as white to avoid other barriers */ 210 makewhite(g, o); /* mark 'o' as white to avoid other barriers */
229 } 211 }
230} 212}
@@ -266,6 +248,7 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
266 global_State *g = G(L); 248 global_State *g = G(L);
267 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); 249 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz));
268 GCObject *o = cast(GCObject *, p + offset); 250 GCObject *o = cast(GCObject *, p + offset);
251 g->GCdebt--;
269 o->marked = luaC_white(g); 252 o->marked = luaC_white(g);
270 o->tt = tt; 253 o->tt = tt;
271 o->next = g->allgc; 254 o->next = g->allgc;
@@ -274,6 +257,9 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
274} 257}
275 258
276 259
260/*
261** create a new collectable object with no offset.
262*/
277GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { 263GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
278 return luaC_newobjdt(L, tt, sz, 0); 264 return luaC_newobjdt(L, tt, sz, 0);
279} 265}
@@ -302,6 +288,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
302** (only closures can), and a userdata's metatable must be a table. 288** (only closures can), and a userdata's metatable must be a table.
303*/ 289*/
304static void reallymarkobject (global_State *g, GCObject *o) { 290static void reallymarkobject (global_State *g, GCObject *o) {
291 g->marked++;
305 switch (o->tt) { 292 switch (o->tt) {
306 case LUA_VSHRSTR: 293 case LUA_VSHRSTR:
307 case LUA_VLNGSTR: { 294 case LUA_VLNGSTR: {
@@ -349,9 +336,9 @@ static void markmt (global_State *g) {
349/* 336/*
350** mark all objects in list of being-finalized 337** mark all objects in list of being-finalized
351*/ 338*/
352static lu_mem markbeingfnz (global_State *g) { 339static l_obj markbeingfnz (global_State *g) {
353 GCObject *o; 340 GCObject *o;
354 lu_mem count = 0; 341 l_obj count = 0;
355 for (o = g->tobefnz; o != NULL; o = o->next) { 342 for (o = g->tobefnz; o != NULL; o = o->next) {
356 count++; 343 count++;
357 markobject(g, o); 344 markobject(g, o);
@@ -371,12 +358,11 @@ static lu_mem markbeingfnz (global_State *g) {
371** upvalues, as they have nothing to be checked. (If the thread gets an 358** upvalues, as they have nothing to be checked. (If the thread gets an
372** upvalue later, it will be linked in the list again.) 359** upvalue later, it will be linked in the list again.)
373*/ 360*/
374static int remarkupvals (global_State *g) { 361static l_obj remarkupvals (global_State *g) {
362 l_obj work = 0;
375 lua_State *thread; 363 lua_State *thread;
376 lua_State **p = &g->twups; 364 lua_State **p = &g->twups;
377 int work = 0; /* estimate of how much work was done here */
378 while ((thread = *p) != NULL) { 365 while ((thread = *p) != NULL) {
379 work++;
380 if (!iswhite(thread) && thread->openupval != NULL) 366 if (!iswhite(thread) && thread->openupval != NULL)
381 p = &thread->twups; /* keep marked thread with upvalues in the list */ 367 p = &thread->twups; /* keep marked thread with upvalues in the list */
382 else { /* thread is not marked or without upvalues */ 368 else { /* thread is not marked or without upvalues */
@@ -386,13 +372,13 @@ static int remarkupvals (global_State *g) {
386 thread->twups = thread; /* mark that it is out of list */ 372 thread->twups = thread; /* mark that it is out of list */
387 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { 373 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
388 lua_assert(getage(uv) <= getage(thread)); 374 lua_assert(getage(uv) <= getage(thread));
389 work++;
390 if (!iswhite(uv)) { /* upvalue already visited? */ 375 if (!iswhite(uv)) { /* upvalue already visited? */
391 lua_assert(upisopen(uv) && isgray(uv)); 376 lua_assert(upisopen(uv) && isgray(uv));
392 markvalue(g, uv->v.p); /* mark its value */ 377 markvalue(g, uv->v.p); /* mark its value */
393 } 378 }
394 } 379 }
395 } 380 }
381 work++;
396 } 382 }
397 return work; 383 return work;
398} 384}
@@ -405,10 +391,15 @@ static void cleargraylists (global_State *g) {
405 391
406 392
407/* 393/*
408** mark root set and reset all gray lists, to start a new collection 394** mark root set and reset all gray lists, to start a new collection.
395** 'marked' is initialized with the number of fixed objects in the state,
396** to count the total number of live objects during a cycle. (That is
397** the metafield names, plus the reserved words, plus "_ENV" plus the
398** memory-error message.)
409*/ 399*/
410static void restartcollection (global_State *g) { 400static void restartcollection (global_State *g) {
411 cleargraylists(g); 401 cleargraylists(g);
402 g->marked = NFIXED;
412 markobject(g, g->mainthread); 403 markobject(g, g->mainthread);
413 markvalue(g, &g->l_registry); 404 markvalue(g, &g->l_registry);
414 markmt(g); 405 markmt(g);
@@ -550,7 +541,7 @@ static void traversestrongtable (global_State *g, Table *h) {
550} 541}
551 542
552 543
553static lu_mem traversetable (global_State *g, Table *h) { 544static void traversetable (global_State *g, Table *h) {
554 const char *weakkey, *weakvalue; 545 const char *weakkey, *weakvalue;
555 const TValue *mode = gfasttm(g, h->metatable, TM_MODE); 546 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
556 TString *smode; 547 TString *smode;
@@ -569,17 +560,15 @@ static lu_mem traversetable (global_State *g, Table *h) {
569 } 560 }
570 else /* not weak */ 561 else /* not weak */
571 traversestrongtable(g, h); 562 traversestrongtable(g, h);
572 return 1 + h->alimit + 2 * allocsizenode(h);
573} 563}
574 564
575 565
576static int traverseudata (global_State *g, Udata *u) { 566static void traverseudata (global_State *g, Udata *u) {
577 int i; 567 int i;
578 markobjectN(g, u->metatable); /* mark its metatable */ 568 markobjectN(g, u->metatable); /* mark its metatable */
579 for (i = 0; i < u->nuvalue; i++) 569 for (i = 0; i < u->nuvalue; i++)
580 markvalue(g, &u->uv[i].uv); 570 markvalue(g, &u->uv[i].uv);
581 genlink(g, obj2gco(u)); 571 genlink(g, obj2gco(u));
582 return 1 + u->nuvalue;
583} 572}
584 573
585 574
@@ -588,7 +577,7 @@ static int traverseudata (global_State *g, Udata *u) {
588** arrays can be larger than needed; the extra slots are filled with 577** arrays can be larger than needed; the extra slots are filled with
589** NULL, so the use of 'markobjectN') 578** NULL, so the use of 'markobjectN')
590*/ 579*/
591static int traverseproto (global_State *g, Proto *f) { 580static void traverseproto (global_State *g, Proto *f) {
592 int i; 581 int i;
593 markobjectN(g, f->source); 582 markobjectN(g, f->source);
594 for (i = 0; i < f->sizek; i++) /* mark literals */ 583 for (i = 0; i < f->sizek; i++) /* mark literals */
@@ -599,29 +588,26 @@ static int traverseproto (global_State *g, Proto *f) {
599 markobjectN(g, f->p[i]); 588 markobjectN(g, f->p[i]);
600 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ 589 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
601 markobjectN(g, f->locvars[i].varname); 590 markobjectN(g, f->locvars[i].varname);
602 return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
603} 591}
604 592
605 593
606static int traverseCclosure (global_State *g, CClosure *cl) { 594static void traverseCclosure (global_State *g, CClosure *cl) {
607 int i; 595 int i;
608 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ 596 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
609 markvalue(g, &cl->upvalue[i]); 597 markvalue(g, &cl->upvalue[i]);
610 return 1 + cl->nupvalues;
611} 598}
612 599
613/* 600/*
614** Traverse a Lua closure, marking its prototype and its upvalues. 601** Traverse a Lua closure, marking its prototype and its upvalues.
615** (Both can be NULL while closure is being created.) 602** (Both can be NULL while closure is being created.)
616*/ 603*/
617static int traverseLclosure (global_State *g, LClosure *cl) { 604static void traverseLclosure (global_State *g, LClosure *cl) {
618 int i; 605 int i;
619 markobjectN(g, cl->p); /* mark its prototype */ 606 markobjectN(g, cl->p); /* mark its prototype */
620 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ 607 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */
621 UpVal *uv = cl->upvals[i]; 608 UpVal *uv = cl->upvals[i];
622 markobjectN(g, uv); /* mark upvalue */ 609 markobjectN(g, uv); /* mark upvalue */
623 } 610 }
624 return 1 + cl->nupvalues;
625} 611}
626 612
627 613
@@ -637,13 +623,13 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
637** (which can only happen in generational mode) or if the traverse is in 623** (which can only happen in generational mode) or if the traverse is in
638** the propagate phase (which can only happen in incremental mode). 624** the propagate phase (which can only happen in incremental mode).
639*/ 625*/
640static int traversethread (global_State *g, lua_State *th) { 626static void traversethread (global_State *g, lua_State *th) {
641 UpVal *uv; 627 UpVal *uv;
642 StkId o = th->stack.p; 628 StkId o = th->stack.p;
643 if (isold(th) || g->gcstate == GCSpropagate) 629 if (isold(th) || g->gcstate == GCSpropagate)
644 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 630 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
645 if (o == NULL) 631 if (o == NULL)
646 return 1; /* stack not completely built yet */ 632 return; /* stack not completely built yet */
647 lua_assert(g->gcstate == GCSatomic || 633 lua_assert(g->gcstate == GCSatomic ||
648 th->openupval == NULL || isintwups(th)); 634 th->openupval == NULL || isintwups(th));
649 for (; o < th->top.p; o++) /* mark live elements in the stack */ 635 for (; o < th->top.p; o++) /* mark live elements in the stack */
@@ -661,34 +647,35 @@ static int traversethread (global_State *g, lua_State *th) {
661 g->twups = th; 647 g->twups = th;
662 } 648 }
663 } 649 }
664 return 1 + stacksize(th);
665} 650}
666 651
667 652
668/* 653/*
669** traverse one gray object, turning it to black. 654** traverse one gray object, turning it to black.
670*/ 655*/
671static lu_mem propagatemark (global_State *g) { 656static void propagatemark (global_State *g) {
672 GCObject *o = g->gray; 657 GCObject *o = g->gray;
673 nw2black(o); 658 nw2black(o);
674 g->gray = *getgclist(o); /* remove from 'gray' list */ 659 g->gray = *getgclist(o); /* remove from 'gray' list */
675 switch (o->tt) { 660 switch (o->tt) {
676 case LUA_VTABLE: return traversetable(g, gco2t(o)); 661 case LUA_VTABLE: traversetable(g, gco2t(o)); break;
677 case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); 662 case LUA_VUSERDATA: traverseudata(g, gco2u(o)); break;
678 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); 663 case LUA_VLCL: traverseLclosure(g, gco2lcl(o)); break;
679 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); 664 case LUA_VCCL: traverseCclosure(g, gco2ccl(o)); break;
680 case LUA_VPROTO: return traverseproto(g, gco2p(o)); 665 case LUA_VPROTO: traverseproto(g, gco2p(o)); break;
681 case LUA_VTHREAD: return traversethread(g, gco2th(o)); 666 case LUA_VTHREAD: traversethread(g, gco2th(o)); break;
682 default: lua_assert(0); return 0; 667 default: lua_assert(0);
683 } 668 }
684} 669}
685 670
686 671
687static lu_mem propagateall (global_State *g) { 672static l_obj propagateall (global_State *g) {
688 lu_mem tot = 0; 673 l_obj work = 0;
689 while (g->gray) 674 while (g->gray) {
690 tot += propagatemark(g); 675 propagatemark(g);
691 return tot; 676 work++;
677 }
678 return work;
692} 679}
693 680
694 681
@@ -697,10 +684,10 @@ static lu_mem propagateall (global_State *g) {
697** Repeat until it converges, that is, nothing new is marked. 'dir' 684** Repeat until it converges, that is, nothing new is marked. 'dir'
698** inverts the direction of the traversals, trying to speed up 685** inverts the direction of the traversals, trying to speed up
699** convergence on chains in the same table. 686** convergence on chains in the same table.
700**
701*/ 687*/
702static void convergeephemerons (global_State *g) { 688static l_obj convergeephemerons (global_State *g) {
703 int changed; 689 int changed;
690 l_obj work = 0;
704 int dir = 0; 691 int dir = 0;
705 do { 692 do {
706 GCObject *w; 693 GCObject *w;
@@ -715,9 +702,11 @@ static void convergeephemerons (global_State *g) {
715 propagateall(g); /* propagate changes */ 702 propagateall(g); /* propagate changes */
716 changed = 1; /* will have to revisit all ephemeron tables */ 703 changed = 1; /* will have to revisit all ephemeron tables */
717 } 704 }
705 work++;
718 } 706 }
719 dir = !dir; /* invert direction next time */ 707 dir = !dir; /* invert direction next time */
720 } while (changed); /* repeat until no more changes */ 708 } while (changed); /* repeat until no more changes */
709 return work;
721} 710}
722 711
723/* }====================================================== */ 712/* }====================================================== */
@@ -733,7 +722,8 @@ static void convergeephemerons (global_State *g) {
733/* 722/*
734** clear entries with unmarked keys from all weaktables in list 'l' 723** clear entries with unmarked keys from all weaktables in list 'l'
735*/ 724*/
736static void clearbykeys (global_State *g, GCObject *l) { 725static l_obj clearbykeys (global_State *g, GCObject *l) {
726 l_obj work = 0;
737 for (; l; l = gco2t(l)->gclist) { 727 for (; l; l = gco2t(l)->gclist) {
738 Table *h = gco2t(l); 728 Table *h = gco2t(l);
739 Node *limit = gnodelast(h); 729 Node *limit = gnodelast(h);
@@ -744,7 +734,9 @@ static void clearbykeys (global_State *g, GCObject *l) {
744 if (isempty(gval(n))) /* is entry empty? */ 734 if (isempty(gval(n))) /* is entry empty? */
745 clearkey(n); /* clear its key */ 735 clearkey(n); /* clear its key */
746 } 736 }
737 work++;
747 } 738 }
739 return work;
748} 740}
749 741
750 742
@@ -752,7 +744,8 @@ static void clearbykeys (global_State *g, GCObject *l) {
752** clear entries with unmarked values from all weaktables in list 'l' up 744** clear entries with unmarked values from all weaktables in list 'l' up
753** to element 'f' 745** to element 'f'
754*/ 746*/
755static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { 747static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
748 l_obj work = 0;
756 for (; l != f; l = gco2t(l)->gclist) { 749 for (; l != f; l = gco2t(l)->gclist) {
757 Table *h = gco2t(l); 750 Table *h = gco2t(l);
758 Node *n, *limit = gnodelast(h); 751 Node *n, *limit = gnodelast(h);
@@ -769,7 +762,9 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
769 if (isempty(gval(n))) /* is entry empty? */ 762 if (isempty(gval(n))) /* is entry empty? */
770 clearkey(n); /* clear its key */ 763 clearkey(n); /* clear its key */
771 } 764 }
765 work++;
772 } 766 }
767 return work;
773} 768}
774 769
775 770
@@ -781,6 +776,7 @@ static void freeupval (lua_State *L, UpVal *uv) {
781 776
782 777
783static void freeobj (lua_State *L, GCObject *o) { 778static void freeobj (lua_State *L, GCObject *o) {
779 G(L)->totalobjs--;
784 switch (o->tt) { 780 switch (o->tt) {
785 case LUA_VPROTO: 781 case LUA_VPROTO:
786 luaF_freeproto(L, gco2p(o)); 782 luaF_freeproto(L, gco2p(o));
@@ -830,10 +826,9 @@ static void freeobj (lua_State *L, GCObject *o) {
830** objects, where a dead object is one marked with the old (non current) 826** objects, where a dead object is one marked with the old (non current)
831** white; change all non-dead objects back to white, preparing for next 827** white; change all non-dead objects back to white, preparing for next
832** collection cycle. Return where to continue the traversal or NULL if 828** collection cycle. Return where to continue the traversal or NULL if
833** list is finished. ('*countout' gets the number of elements traversed.) 829** list is finished.
834*/ 830*/
835static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, 831static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) {
836 int *countout) {
837 global_State *g = G(L); 832 global_State *g = G(L);
838 int ow = otherwhite(g); 833 int ow = otherwhite(g);
839 int i; 834 int i;
@@ -850,8 +845,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
850 p = &curr->next; /* go to next element */ 845 p = &curr->next; /* go to next element */
851 } 846 }
852 } 847 }
853 if (countout)
854 *countout = i; /* number of elements traversed */
855 return (*p == NULL) ? NULL : p; 848 return (*p == NULL) ? NULL : p;
856} 849}
857 850
@@ -862,7 +855,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
862static GCObject **sweeptolive (lua_State *L, GCObject **p) { 855static GCObject **sweeptolive (lua_State *L, GCObject **p) {
863 GCObject **old = p; 856 GCObject **old = p;
864 do { 857 do {
865 p = sweeplist(L, p, 1, NULL); 858 p = sweeplist(L, p, 1);
866 } while (p == old); 859 } while (p == old);
867 return p; 860 return p;
868} 861}
@@ -881,11 +874,8 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) {
881*/ 874*/
882static void checkSizes (lua_State *L, global_State *g) { 875static void checkSizes (lua_State *L, global_State *g) {
883 if (!g->gcemergency) { 876 if (!g->gcemergency) {
884 if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ 877 if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
885 l_mem olddebt = g->GCdebt;
886 luaS_resize(L, g->strt.size / 2); 878 luaS_resize(L, g->strt.size / 2);
887 g->GCestimate += g->GCdebt - olddebt; /* correct estimate */
888 }
889 } 879 }
890} 880}
891 881
@@ -944,18 +934,6 @@ static void GCTM (lua_State *L) {
944 934
945 935
946/* 936/*
947** Call a few finalizers
948*/
949static int runafewfinalizers (lua_State *L, int n) {
950 global_State *g = G(L);
951 int i;
952 for (i = 0; i < n && g->tobefnz; i++)
953 GCTM(L); /* call one finalizer */
954 return i;
955}
956
957
958/*
959** call all pending finalizers 937** call all pending finalizers
960*/ 938*/
961static void callallpendingfinalizers (lua_State *L) { 939static void callallpendingfinalizers (lua_State *L) {
@@ -1063,20 +1041,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
1063 1041
1064/* 1042/*
1065** Set the "time" to wait before starting a new GC cycle; cycle will 1043** Set the "time" to wait before starting a new GC cycle; cycle will
1066** start when memory use hits the threshold of ('estimate' * pause / 1044** start when number of objects in use hits the threshold of
1067** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, 1045** approximately (marked * pause / 100).
1068** because Lua cannot even start with less than PAUSEADJ bytes).
1069*/ 1046*/
1070static void setpause (global_State *g) { 1047static void setpause (global_State *g) {
1071 l_mem threshold, debt; 1048 l_obj threshold = applygcparam(g, gcpause, g->marked);
1072 int pause = getgcparam(g->gcpause); 1049 l_obj debt = threshold - gettotalobjs(g);
1073 l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ 1050 if (debt < 0) debt = 0;
1074 lua_assert(estimate > 0);
1075 threshold = (pause < MAX_LMEM / estimate) /* overflow? */
1076 ? estimate * pause /* no overflow */
1077 : MAX_LMEM; /* overflow; truncate to maximum */
1078 debt = gettotalbytes(g) - threshold;
1079 if (debt > 0) debt = 0;
1080 luaE_setdebt(g, debt); 1051 luaE_setdebt(g, debt);
1081} 1052}
1082 1053
@@ -1316,18 +1287,17 @@ static void atomic2gen (lua_State *L, global_State *g) {
1316 sweep2old(L, &g->tobefnz); 1287 sweep2old(L, &g->tobefnz);
1317 1288
1318 g->gckind = KGC_GEN; 1289 g->gckind = KGC_GEN;
1319 g->lastatomic = 0; 1290 g->GClastmajor = gettotalobjs(g); /* base for memory control */
1320 g->GCestimate = gettotalbytes(g); /* base for memory control */
1321 finishgencycle(L, g); 1291 finishgencycle(L, g);
1322} 1292}
1323 1293
1324 1294
1325/* 1295/*
1326** Set debt for the next minor collection, which will happen when 1296** Set debt for the next minor collection, which will happen when
1327** memory grows 'genminormul'%. 1297** total number of objects grows 'genminormul'%.
1328*/ 1298*/
1329static void setminordebt (global_State *g) { 1299static void setminordebt (global_State *g) {
1330 luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); 1300 luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g)));
1331} 1301}
1332 1302
1333 1303
@@ -1337,14 +1307,12 @@ static void setminordebt (global_State *g) {
1337** are cleared. Then, turn all objects into old and finishes the 1307** are cleared. Then, turn all objects into old and finishes the
1338** collection. 1308** collection.
1339*/ 1309*/
1340static lu_mem entergen (lua_State *L, global_State *g) { 1310static void entergen (lua_State *L, global_State *g) {
1341 lu_mem numobjs;
1342 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ 1311 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */
1343 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1312 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1344 numobjs = atomic(L); /* propagates all and then do the atomic stuff */ 1313 atomic(L); /* propagates all and then do the atomic stuff */
1345 atomic2gen(L, g); 1314 atomic2gen(L, g);
1346 setminordebt(g); /* set debt assuming next cycle will be minor */ 1315 setminordebt(g); /* set debt assuming next cycle will be minor */
1347 return numobjs;
1348} 1316}
1349 1317
1350 1318
@@ -1361,7 +1329,6 @@ static void enterinc (global_State *g) {
1361 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1329 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1362 g->gcstate = GCSpause; 1330 g->gcstate = GCSpause;
1363 g->gckind = KGC_INC; 1331 g->gckind = KGC_INC;
1364 g->lastatomic = 0;
1365} 1332}
1366 1333
1367 1334
@@ -1370,111 +1337,75 @@ static void enterinc (global_State *g) {
1370*/ 1337*/
1371void luaC_changemode (lua_State *L, int newmode) { 1338void luaC_changemode (lua_State *L, int newmode) {
1372 global_State *g = G(L); 1339 global_State *g = G(L);
1373 if (newmode != g->gckind) { 1340 if (newmode != g->gckind) { /* does it need to change? */
1374 if (newmode == KGC_GEN) /* entering generational mode? */ 1341 if (newmode == KGC_INC) { /* entering incremental mode? */
1342 if (g->gckind == KGC_GENMAJOR)
1343 g->gckind = KGC_INC; /* already incremental but in name */
1344 else
1345 enterinc(g); /* entering incremental mode */
1346 }
1347 else {
1348 lua_assert(newmode == KGC_GEN);
1375 entergen(L, g); 1349 entergen(L, g);
1376 else 1350 }
1377 enterinc(g); /* entering incremental mode */
1378 } 1351 }
1379 g->lastatomic = 0;
1380} 1352}
1381 1353
1382 1354
1383/* 1355/*
1384** Does a full collection in generational mode. 1356** Does a full collection in generational mode.
1385*/ 1357*/
1386static lu_mem fullgen (lua_State *L, global_State *g) { 1358static void fullgen (lua_State *L, global_State *g) {
1387 enterinc(g); 1359 enterinc(g);
1388 return entergen(L, g); 1360 entergen(L, g);
1389} 1361}
1390 1362
1391 1363
1392/* 1364/*
1393** Does a major collection after last collection was a "bad collection". 1365** Does a major collector up to the atomic phase and then either
1394** 1366** returns to minor collections or stays doing major ones. If the
1395** When the program is building a big structure, it allocates lots of 1367** number of objects collected this time (numobjs - marked) is more than
1396** memory but generates very little garbage. In those scenarios, 1368** half the number of objects created since the last major collection
1397** the generational mode just wastes time doing small collections, and 1369** (numobjs - lastmajor), it goes back to minor collections.
1398** major collections are frequently what we call a "bad collection", a 1370*/
1399** collection that frees too few objects. To avoid the cost of switching 1371static void genmajorstep (lua_State *L, global_State *g) {
1400** between generational mode and the incremental mode needed for full 1372 l_obj lastmajor = g->GClastmajor; /* count from last collection */
1401** (major) collections, the collector tries to stay in incremental mode 1373 l_obj numobjs = gettotalobjs(g); /* current count */
1402** after a bad collection, and to switch back to generational mode only
1403** after a "good" collection (one that traverses less than 9/8 objects
1404** of the previous one).
1405** The collector must choose whether to stay in incremental mode or to
1406** switch back to generational mode before sweeping. At this point, it
1407** does not know the real memory in use, so it cannot use memory to
1408** decide whether to return to generational mode. Instead, it uses the
1409** number of objects traversed (returned by 'atomic') as a proxy. The
1410** field 'g->lastatomic' keeps this count from the last collection.
1411** ('g->lastatomic != 0' also means that the last collection was bad.)
1412*/
1413static void stepgenfull (lua_State *L, global_State *g) {
1414 lu_mem newatomic; /* count of traversed objects */
1415 lu_mem lastatomic = g->lastatomic; /* count from last collection */
1416 if (g->gckind == KGC_GEN) /* still in generational mode? */
1417 enterinc(g); /* enter incremental mode */
1418 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1374 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1419 newatomic = atomic(L); /* mark everybody */ 1375 atomic(L); /* mark everybody */
1420 if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ 1376 if ((numobjs - g->marked) > ((numobjs - lastmajor) >> 1)) {
1421 atomic2gen(L, g); /* return to generational mode */ 1377 atomic2gen(L, g); /* return to generational mode */
1422 setminordebt(g); 1378 setminordebt(g);
1423 } 1379 }
1424 else { /* another bad collection; stay in incremental mode */ 1380 else { /* bad collection; stay in major mode */
1425 g->GCestimate = gettotalbytes(g); /* first estimate */
1426 entersweep(L); 1381 entersweep(L);
1427 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1382 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1428 setpause(g); 1383 setpause(g);
1429 g->lastatomic = newatomic; 1384 g->GClastmajor = gettotalobjs(g);
1430 } 1385 }
1431} 1386}
1432 1387
1433 1388
1434/* 1389/*
1435** Does a generational "step". 1390** Does a generational "step". If the total number of objects grew
1436** Usually, this means doing a minor collection and setting the debt to 1391** more than 'majormul'% since the last major collection, does a
1437** make another collection when memory grows 'genminormul'% larger. 1392** major collection. Otherwise, does a minor collection.
1438**
1439** However, there are exceptions. If memory grows 'genmajormul'%
1440** larger than it was at the end of the last major collection (kept
1441** in 'g->GCestimate'), the function does a major collection. At the
1442** end, it checks whether the major collection was able to free a
1443** decent amount of memory (at least half the growth in memory since
1444** previous major collection). If so, the collector keeps its state,
1445** and the next collection will probably be minor again. Otherwise,
1446** we have what we call a "bad collection". In that case, set the field
1447** 'g->lastatomic' to signal that fact, so that the next collection will
1448** go to 'stepgenfull'.
1449**
1450** 'GCdebt <= 0' means an explicit call to GC step with "size" zero;
1451** in that case, do a minor collection.
1452*/ 1393*/
1453static void genstep (lua_State *L, global_State *g) { 1394static void genstep (lua_State *L, global_State *g) {
1454 if (g->lastatomic != 0) /* last collection was a bad one? */ 1395 l_obj majorbase = g->GClastmajor; /* count after last major collection */
1455 stepgenfull(L, g); /* do a full step */ 1396 l_obj majorinc = applygcparam(g, genmajormul, majorbase);
1456 else { 1397 if (gettotalobjs(g) > majorbase + majorinc && 0) {
1457 lu_mem majorbase = g->GCestimate; /* memory after last major collection */ 1398 /* do a major collection */
1458 lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); 1399 enterinc(g);
1459 if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { 1400 g->gckind = KGC_GENMAJOR;
1460 lu_mem numobjs = fullgen(L, g); /* do a major collection */ 1401 genmajorstep(L, g);
1461 if (gettotalbytes(g) < majorbase + (majorinc / 2)) { 1402 }
1462 /* collected at least half of memory growth since last major 1403 else { /* regular case; do a minor collection */
1463 collection; keep doing minor collections. */ 1404 g->marked = 0;
1464 lua_assert(g->lastatomic == 0); 1405 youngcollection(L, g);
1465 } 1406 setminordebt(g);
1466 else { /* bad collection */ 1407 lua_assert(g->GClastmajor == majorbase);
1467 g->lastatomic = numobjs; /* signal that last collection was bad */
1468 setpause(g); /* do a long wait for next (major) collection */
1469 }
1470 }
1471 else { /* regular case; do a minor collection */
1472 youngcollection(L, g);
1473 setminordebt(g);
1474 g->GCestimate = majorbase; /* preserve base value */
1475 }
1476 } 1408 }
1477 lua_assert(isdecGCmodegen(g));
1478} 1409}
1479 1410
1480/* }====================================================== */ 1411/* }====================================================== */
@@ -1533,9 +1464,9 @@ void luaC_freeallobjects (lua_State *L) {
1533} 1464}
1534 1465
1535 1466
1536static lu_mem atomic (lua_State *L) { 1467static l_obj atomic (lua_State *L) {
1468 l_obj work = 0;
1537 global_State *g = G(L); 1469 global_State *g = G(L);
1538 lu_mem work = 0;
1539 GCObject *origweak, *origall; 1470 GCObject *origweak, *origall;
1540 GCObject *grayagain = g->grayagain; /* save original list */ 1471 GCObject *grayagain = g->grayagain; /* save original list */
1541 g->grayagain = NULL; 1472 g->grayagain = NULL;
@@ -1552,50 +1483,44 @@ static lu_mem atomic (lua_State *L) {
1552 work += propagateall(g); /* propagate changes */ 1483 work += propagateall(g); /* propagate changes */
1553 g->gray = grayagain; 1484 g->gray = grayagain;
1554 work += propagateall(g); /* traverse 'grayagain' list */ 1485 work += propagateall(g); /* traverse 'grayagain' list */
1555 convergeephemerons(g); 1486 work += convergeephemerons(g);
1556 /* at this point, all strongly accessible objects are marked. */ 1487 /* at this point, all strongly accessible objects are marked. */
1557 /* Clear values from weak tables, before checking finalizers */ 1488 /* Clear values from weak tables, before checking finalizers */
1558 clearbyvalues(g, g->weak, NULL); 1489 work += clearbyvalues(g, g->weak, NULL);
1559 clearbyvalues(g, g->allweak, NULL); 1490 work += clearbyvalues(g, g->allweak, NULL);
1560 origweak = g->weak; origall = g->allweak; 1491 origweak = g->weak; origall = g->allweak;
1561 separatetobefnz(g, 0); /* separate objects to be finalized */ 1492 separatetobefnz(g, 0); /* separate objects to be finalized */
1562 work += markbeingfnz(g); /* mark objects that will be finalized */ 1493 work += markbeingfnz(g); /* mark objects that will be finalized */
1563 work += propagateall(g); /* remark, to propagate 'resurrection' */ 1494 work += propagateall(g); /* remark, to propagate 'resurrection' */
1564 convergeephemerons(g); 1495 work += convergeephemerons(g);
1565 /* at this point, all resurrected objects are marked. */ 1496 /* at this point, all resurrected objects are marked. */
1566 /* remove dead objects from weak tables */ 1497 /* remove dead objects from weak tables */
1567 clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ 1498 work += clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */
1568 clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ 1499 work += clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */
1569 /* clear values from resurrected weak tables */ 1500 /* clear values from resurrected weak tables */
1570 clearbyvalues(g, g->weak, origweak); 1501 work += clearbyvalues(g, g->weak, origweak);
1571 clearbyvalues(g, g->allweak, origall); 1502 work += clearbyvalues(g, g->allweak, origall);
1572 luaS_clearcache(g); 1503 luaS_clearcache(g);
1573 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1504 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
1574 lua_assert(g->gray == NULL); 1505 lua_assert(g->gray == NULL);
1575 return work; /* estimate of slots marked by 'atomic' */ 1506 return work;
1576} 1507}
1577 1508
1578 1509
1579static int sweepstep (lua_State *L, global_State *g, 1510static void sweepstep (lua_State *L, global_State *g,
1580 int nextstate, GCObject **nextlist) { 1511 int nextstate, GCObject **nextlist) {
1581 if (g->sweepgc) { 1512 if (g->sweepgc)
1582 l_mem olddebt = g->GCdebt; 1513 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
1583 int count;
1584 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count);
1585 g->GCestimate += g->GCdebt - olddebt; /* update estimate */
1586 return count;
1587 }
1588 else { /* enter next state */ 1514 else { /* enter next state */
1589 g->gcstate = nextstate; 1515 g->gcstate = nextstate;
1590 g->sweepgc = nextlist; 1516 g->sweepgc = nextlist;
1591 return 0; /* no work done */
1592 } 1517 }
1593} 1518}
1594 1519
1595 1520
1596static lu_mem singlestep (lua_State *L) { 1521static l_obj singlestep (lua_State *L) {
1597 global_State *g = G(L); 1522 global_State *g = G(L);
1598 lu_mem work; 1523 l_obj work;
1599 lua_assert(!g->gcstopem); /* collector is not reentrant */ 1524 lua_assert(!g->gcstopem); /* collector is not reentrant */
1600 g->gcstopem = 1; /* no emergency collections while collecting */ 1525 g->gcstopem = 1; /* no emergency collections while collecting */
1601 switch (g->gcstate) { 1526 switch (g->gcstate) {
@@ -1610,26 +1535,30 @@ static lu_mem singlestep (lua_State *L) {
1610 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1535 g->gcstate = GCSenteratomic; /* finish propagate phase */
1611 work = 0; 1536 work = 0;
1612 } 1537 }
1613 else 1538 else {
1614 work = propagatemark(g); /* traverse one gray object */ 1539 propagatemark(g); /* traverse one gray object */
1540 work = 1;
1541 }
1615 break; 1542 break;
1616 } 1543 }
1617 case GCSenteratomic: { 1544 case GCSenteratomic: {
1618 work = atomic(L); /* work is what was traversed by 'atomic' */ 1545 work = atomic(L);
1619 entersweep(L); 1546 entersweep(L);
1620 g->GCestimate = gettotalbytes(g); /* first estimate */
1621 break; 1547 break;
1622 } 1548 }
1623 case GCSswpallgc: { /* sweep "regular" objects */ 1549 case GCSswpallgc: { /* sweep "regular" objects */
1624 work = sweepstep(L, g, GCSswpfinobj, &g->finobj); 1550 sweepstep(L, g, GCSswpfinobj, &g->finobj);
1551 work = GCSWEEPMAX;
1625 break; 1552 break;
1626 } 1553 }
1627 case GCSswpfinobj: { /* sweep objects with finalizers */ 1554 case GCSswpfinobj: { /* sweep objects with finalizers */
1628 work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1555 sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1556 work = GCSWEEPMAX;
1629 break; 1557 break;
1630 } 1558 }
1631 case GCSswptobefnz: { /* sweep objects to be finalized */ 1559 case GCSswptobefnz: { /* sweep objects to be finalized */
1632 work = sweepstep(L, g, GCSswpend, NULL); 1560 sweepstep(L, g, GCSswpend, NULL);
1561 work = GCSWEEPMAX;
1633 break; 1562 break;
1634 } 1563 }
1635 case GCSswpend: { /* finish sweeps */ 1564 case GCSswpend: { /* finish sweeps */
@@ -1638,10 +1567,11 @@ static lu_mem singlestep (lua_State *L) {
1638 work = 0; 1567 work = 0;
1639 break; 1568 break;
1640 } 1569 }
1641 case GCScallfin: { /* call remaining finalizers */ 1570 case GCScallfin: { /* call finalizers */
1642 if (g->tobefnz && !g->gcemergency) { 1571 if (g->tobefnz && !g->gcemergency) {
1643 g->gcstopem = 0; /* ok collections during finalizers */ 1572 g->gcstopem = 0; /* ok collections during finalizers */
1644 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; 1573 GCTM(L); /* call one finalizer */
1574 work = 1;
1645 } 1575 }
1646 else { /* emergency mode or no more finalizers */ 1576 else { /* emergency mode or no more finalizers */
1647 g->gcstate = GCSpause; /* finish collection */ 1577 g->gcstate = GCSpause; /* finish collection */
@@ -1676,20 +1606,16 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1676** controls when next step will be performed. 1606** controls when next step will be performed.
1677*/ 1607*/
1678static void incstep (lua_State *L, global_State *g) { 1608static void incstep (lua_State *L, global_State *g) {
1679 int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ 1609 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1680 l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; 1610 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1681 l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem))
1682 ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul
1683 : MAX_LMEM; /* overflow; keep maximum value */
1684 do { /* repeat until pause or enough "credit" (negative debt) */ 1611 do { /* repeat until pause or enough "credit" (negative debt) */
1685 lu_mem work = singlestep(L); /* perform one single step */ 1612 l_obj work = singlestep(L); /* perform one single step */
1686 debt -= work; 1613 work2do -= work;
1687 } while (debt > -stepsize && g->gcstate != GCSpause); 1614 } while (work2do > 0 && g->gcstate != GCSpause);
1688 if (g->gcstate == GCSpause) 1615 if (g->gcstate == GCSpause)
1689 setpause(g); /* pause until next cycle */ 1616 setpause(g); /* pause until next cycle */
1690 else { 1617 else {
1691 debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ 1618 luaE_setdebt(g, stepsize);
1692 luaE_setdebt(g, debt);
1693 } 1619 }
1694} 1620}
1695 1621
@@ -1700,13 +1626,21 @@ static void incstep (lua_State *L, global_State *g) {
1700*/ 1626*/
1701void luaC_step (lua_State *L) { 1627void luaC_step (lua_State *L) {
1702 global_State *g = G(L); 1628 global_State *g = G(L);
1629 lua_assert(!g->gcemergency);
1703 if (!gcrunning(g)) /* not running? */ 1630 if (!gcrunning(g)) /* not running? */
1704 luaE_setdebt(g, -2000); 1631 luaE_setdebt(g, 2000);
1705 else { 1632 else {
1706 if(isdecGCmodegen(g)) 1633 switch (g->gckind) {
1707 genstep(L, g); 1634 case KGC_INC:
1708 else 1635 incstep(L, g);
1709 incstep(L, g); 1636 break;
1637 case KGC_GEN:
1638 genstep(L, g);
1639 break;
1640 case KGC_GENMAJOR:
1641 genmajorstep(L, g);
1642 break;
1643 }
1710 } 1644 }
1711} 1645}
1712 1646
@@ -1726,8 +1660,8 @@ static void fullinc (lua_State *L, global_State *g) {
1726 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1660 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1727 g->gcstate = GCSenteratomic; /* go straight to atomic phase ??? */ 1661 g->gcstate = GCSenteratomic; /* go straight to atomic phase ??? */
1728 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ 1662 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1729 /* estimate must be correct after a full GC cycle */ 1663 /* 'marked' must be correct after a full GC cycle */
1730 lua_assert(g->GCestimate == gettotalbytes(g)); 1664 lua_assert(g->marked == gettotalobjs(g));
1731 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1665 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1732 setpause(g); 1666 setpause(g);
1733} 1667}
@@ -1742,10 +1676,10 @@ void luaC_fullgc (lua_State *L, int isemergency) {
1742 global_State *g = G(L); 1676 global_State *g = G(L);
1743 lua_assert(!g->gcemergency); 1677 lua_assert(!g->gcemergency);
1744 g->gcemergency = isemergency; /* set flag */ 1678 g->gcemergency = isemergency; /* set flag */
1745 if (g->gckind == KGC_INC) 1679 if (g->gckind == KGC_GEN)
1746 fullinc(L, g);
1747 else
1748 fullgen(L, g); 1680 fullgen(L, g);
1681 else
1682 fullinc(L, g);
1749 g->gcemergency = 0; 1683 g->gcemergency = 0;
1750} 1684}
1751 1685
diff --git a/lgc.h b/lgc.h
index 538f6edc..959465ec 100644
--- a/lgc.h
+++ b/lgc.h
@@ -8,6 +8,9 @@
8#define lgc_h 8#define lgc_h
9 9
10 10
11#include <stddef.h>
12
13
11#include "lobject.h" 14#include "lobject.h"
12#include "lstate.h" 15#include "lstate.h"
13 16
@@ -122,31 +125,21 @@
122 125
123 126
124/* Default Values for GC parameters */ 127/* Default Values for GC parameters */
125#define LUAI_GENMAJORMUL 100
126#define LUAI_GENMINORMUL 20
127 128
128/* wait memory to double before starting new cycle */ 129/* generational */
129#define LUAI_GCPAUSE 200
130 130
131/* 131#define LUAI_GENMAJORMUL 100 /* major multiplier */
132** some gc parameters are stored divided by 4 to allow a maximum value 132#define LUAI_GENMINORMUL 20 /* minor multiplier */
133** up to 1023 in a 'lu_byte'.
134*/
135#define getgcparam(p) ((p) * 4)
136#define setgcparam(p,v) ((p) = (v) / 4)
137 133
138#define LUAI_GCMUL 100 134/* incremental */
139 135
140/* how much to allocate before next GC step (log2) */ 136/* wait memory to double before starting new cycle */
141#define LUAI_GCSTEPSIZE 13 /* 8 KB */ 137#define LUAI_GCPAUSE 200
142 138
139#define LUAI_GCMUL 300 /* step multiplier */
143 140
144/* 141/* how many objects to allocate before next GC step (log2) */
145** Check whether the declared GC mode is generational. While in 142#define LUAI_GCSTEPSIZE 8 /* 256 objects */
146** generational mode, the collector can go temporarily to incremental
147** mode to improve performance. This is signaled by 'g->lastatomic != 0'.
148*/
149#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0)
150 143
151 144
152/* 145/*
@@ -157,15 +150,38 @@
157#define GCSTPCLS 4 /* bit true when closing Lua state */ 150#define GCSTPCLS 4 /* bit true when closing Lua state */
158#define gcrunning(g) ((g)->gcstp == 0) 151#define gcrunning(g) ((g)->gcstp == 0)
159 152
153/*
154** Macros to set and apply GC parameters. GC parameters are given in
155** percentage points, but are stored as lu_byte. To reduce their
156** values and avoid repeated divisions by 100, these macros store
157** the original parameter multiplied by 2^n and divided by 100.
158** To apply them, the value is divided by 2^n (a shift) and then
159** multiplied by the stored parameter, yielding
160** value / 2^n * (original parameter * 2^n / 100), or approximately
161** (value * original parameter / 100).
162**
163** For most parameters, which are typically larger than 100%, 2^n is
164** 16 (2^4), allowing maximum values up to 1599. For the minor
165** multiplier, which is typically smaller, 2^n is 64 (2^6) to allow more
166** precision.
167*/
168#define gcparamshift(p) \
169 (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4)
170
171#define setgcparam(g,p,v) \
172 (g->p = (cast_uint(v) << gcparamshift(p)) / 100u)
173#define applygcparam(g,p,v) (((v) >> gcparamshift(p)) * g->p)
174
175
160 176
161/* 177/*
162** Does one step of collection when debt becomes positive. 'pre'/'pos' 178** Does one step of collection when debt becomes zero. 'pre'/'pos'
163** allows some adjustments to be done only when needed. macro 179** allows some adjustments to be done only when needed. macro
164** 'condchangemem' is used only for heavy tests (forcing a full 180** 'condchangemem' is used only for heavy tests (forcing a full
165** GC cycle on every opportunity) 181** GC cycle on every opportunity)
166*/ 182*/
167#define luaC_condGC(L,pre,pos) \ 183#define luaC_condGC(L,pre,pos) \
168 { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ 184 { if (G(L)->GCdebt <= 0) { pre; luaC_step(L); pos;}; \
169 condchangemem(L,pre,pos); } 185 condchangemem(L,pre,pos); }
170 186
171/* more often than not, 'pre'/'pos' are empty */ 187/* more often than not, 'pre'/'pos' are empty */
diff --git a/linit.c b/linit.c
index 69808f84..675fb65f 100644
--- a/linit.c
+++ b/linit.c
@@ -8,21 +8,6 @@
8#define linit_c 8#define linit_c
9#define LUA_LIB 9#define LUA_LIB
10 10
11/*
12** If you embed Lua in your program and need to open the standard
13** libraries, call luaL_openlibs in your program. If you need a
14** different set of libraries, copy this file to your project and edit
15** it to suit your needs.
16**
17** You can also *preload* libraries, so that a later 'require' can
18** open the library, which is already linked to the application.
19** For that, do the following code:
20**
21** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
22** lua_pushcfunction(L, luaopen_modname);
23** lua_setfield(L, -2, modname);
24** lua_pop(L, 1); // remove PRELOAD table
25*/
26 11
27#include "lprefix.h" 12#include "lprefix.h"
28 13
@@ -36,30 +21,44 @@
36 21
37 22
38/* 23/*
39** these libs are loaded by lua.c and are readily available to any Lua 24** Standard Libraries
40** program
41*/ 25*/
42static const luaL_Reg loadedlibs[] = { 26static const luaL_Reg stdlibs[] = {
43 {LUA_GNAME, luaopen_base}, 27 {LUA_GNAME, luaopen_base},
44 {LUA_LOADLIBNAME, luaopen_package}, 28 {LUA_LOADLIBNAME, luaopen_package},
29
45 {LUA_COLIBNAME, luaopen_coroutine}, 30 {LUA_COLIBNAME, luaopen_coroutine},
46 {LUA_TABLIBNAME, luaopen_table}, 31 {LUA_DBLIBNAME, luaopen_debug},
47 {LUA_IOLIBNAME, luaopen_io}, 32 {LUA_IOLIBNAME, luaopen_io},
33 {LUA_MATHLIBNAME, luaopen_math},
48 {LUA_OSLIBNAME, luaopen_os}, 34 {LUA_OSLIBNAME, luaopen_os},
49 {LUA_STRLIBNAME, luaopen_string}, 35 {LUA_STRLIBNAME, luaopen_string},
50 {LUA_MATHLIBNAME, luaopen_math}, 36 {LUA_TABLIBNAME, luaopen_table},
51 {LUA_UTF8LIBNAME, luaopen_utf8}, 37 {LUA_UTF8LIBNAME, luaopen_utf8},
52 {LUA_DBLIBNAME, luaopen_debug}, 38
53 {NULL, NULL} 39 {NULL, NULL}
54}; 40};
55 41
56 42
57LUALIB_API void luaL_openlibs (lua_State *L) { 43/*
44** require selected standard libraries and add the others to the
45** preload table.
46*/
47LUALIB_API void luaL_openselectedlibs (lua_State *L, int what) {
48 int mask = 1;
58 const luaL_Reg *lib; 49 const luaL_Reg *lib;
59 /* "require" functions from 'loadedlibs' and set results to global table */ 50 luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
60 for (lib = loadedlibs; lib->func; lib++) { 51 for (lib = stdlibs; lib->func; (lib++, mask <<= 1)) {
61 luaL_requiref(L, lib->name, lib->func, 1); 52 if (what & mask) { /* selected? */
62 lua_pop(L, 1); /* remove lib */ 53 luaL_requiref(L, lib->name, lib->func, 1); /* require library */
54 lua_pop(L, 1); /* remove result from the stack */
55 }
56 else { /* add library to PRELOAD table */
57 lua_pushcfunction(L, lib->func);
58 lua_setfield(L, -2, lib->name);
59 }
63 } 60 }
61 lua_assert((mask >> 1) == LUA_UTF8LIBK);
62 lua_pop(L, 1); // remove PRELOAD table
64} 63}
65 64
diff --git a/llimits.h b/llimits.h
index 1c826f7b..47dee9a6 100644
--- a/llimits.h
+++ b/llimits.h
@@ -16,21 +16,25 @@
16 16
17 17
18/* 18/*
19** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count 19** 'lu_mem' is an unsigned integer big enough to count the total memory
20** the total memory used by Lua (in bytes). Usually, 'size_t' and 20** used by Lua (in bytes). 'l_obj' is a signed integer big enough to
21** count the total number of objects used by Lua. (It is signed due
22** to the use of debt in several computations.) Usually, 'size_t' and
21** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. 23** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
22*/ 24*/
23#if defined(LUAI_MEM) /* { external definitions? */ 25#if defined(LUAI_MEM) /* { external definitions? */
24typedef LUAI_UMEM lu_mem; 26typedef LUAI_UMEM lu_mem;
25typedef LUAI_MEM l_mem; 27typedef LUAI_MEM l_obj;
26#elif LUAI_IS32INT /* }{ */ 28#elif LUAI_IS32INT /* }{ */
27typedef size_t lu_mem; 29typedef size_t lu_mem;
28typedef ptrdiff_t l_mem; 30typedef ptrdiff_t l_obj;
29#else /* 16-bit ints */ /* }{ */ 31#else /* 16-bit ints */ /* }{ */
30typedef unsigned long lu_mem; 32typedef unsigned long lu_mem;
31typedef long l_mem; 33typedef long l_obj;
32#endif /* } */ 34#endif /* } */
33 35
36#define MAX_LOBJ cast(l_obj, ~cast(lu_mem, 0) >> 1)
37
34 38
35/* chars used as small naturals (so that 'char' is reserved for characters) */ 39/* chars used as small naturals (so that 'char' is reserved for characters) */
36typedef unsigned char lu_byte; 40typedef unsigned char lu_byte;
@@ -45,11 +49,6 @@ typedef signed char ls_byte;
45 : (size_t)(LUA_MAXINTEGER)) 49 : (size_t)(LUA_MAXINTEGER))
46 50
47 51
48#define MAX_LUMEM ((lu_mem)(~(lu_mem)0))
49
50#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1))
51
52
53#define MAX_INT INT_MAX /* maximum value of an int */ 52#define MAX_INT INT_MAX /* maximum value of an int */
54 53
55 54
@@ -57,7 +56,7 @@ typedef signed char ls_byte;
57** floor of the log2 of the maximum signed value for integral type 't'. 56** floor of the log2 of the maximum signed value for integral type 't'.
58** (That is, maximum 'n' such that '2^n' fits in the given signed type.) 57** (That is, maximum 'n' such that '2^n' fits in the given signed type.)
59*/ 58*/
60#define log2maxs(t) (sizeof(t) * 8 - 2) 59#define log2maxs(t) cast_int(sizeof(t) * 8 - 2)
61 60
62 61
63/* 62/*
diff --git a/lmathlib.c b/lmathlib.c
index f140d623..c0a75f06 100644
--- a/lmathlib.c
+++ b/lmathlib.c
@@ -620,28 +620,18 @@ static void setseed (lua_State *L, Rand64 *state,
620} 620}
621 621
622 622
623/*
624** Set a "random" seed. To get some randomness, use the current time
625** and the address of 'L' (in case the machine does address space layout
626** randomization).
627*/
628static void randseed (lua_State *L, RanState *state) {
629 lua_Unsigned seed1 = (lua_Unsigned)time(NULL);
630 lua_Unsigned seed2 = (lua_Unsigned)(size_t)L;
631 setseed(L, state->s, seed1, seed2);
632}
633
634
635static int math_randomseed (lua_State *L) { 623static int math_randomseed (lua_State *L) {
636 RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); 624 RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
625 lua_Unsigned n1, n2;
637 if (lua_isnone(L, 1)) { 626 if (lua_isnone(L, 1)) {
638 randseed(L, state); 627 n1 = luaL_makeseed(L); /* "random" seed */
628 n2 = I2UInt(nextrand(state->s)); /* in case seed is not that random... */
639 } 629 }
640 else { 630 else {
641 lua_Integer n1 = luaL_checkinteger(L, 1); 631 n1 = luaL_checkinteger(L, 1);
642 lua_Integer n2 = luaL_optinteger(L, 2, 0); 632 n2 = luaL_optinteger(L, 2, 0);
643 setseed(L, state->s, n1, n2);
644 } 633 }
634 setseed(L, state->s, n1, n2);
645 return 2; /* return seeds */ 635 return 2; /* return seeds */
646} 636}
647 637
@@ -658,7 +648,7 @@ static const luaL_Reg randfuncs[] = {
658*/ 648*/
659static void setrandfunc (lua_State *L) { 649static void setrandfunc (lua_State *L) {
660 RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0); 650 RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0);
661 randseed(L, state); /* initialize with a "random" seed */ 651 setseed(L, state->s, luaL_makeseed(L), 0); /* initialize with random seed */
662 lua_pop(L, 2); /* remove pushed seeds */ 652 lua_pop(L, 2); /* remove pushed seeds */
663 luaL_setfuncs(L, randfuncs, 1); 653 luaL_setfuncs(L, randfuncs, 1);
664} 654}
diff --git a/lmem.c b/lmem.c
index 9800a86f..dfd8a49b 100644
--- a/lmem.c
+++ b/lmem.c
@@ -151,7 +151,7 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) {
151 global_State *g = G(L); 151 global_State *g = G(L);
152 lua_assert((osize == 0) == (block == NULL)); 152 lua_assert((osize == 0) == (block == NULL));
153 callfrealloc(g, block, osize, 0); 153 callfrealloc(g, block, osize, 0);
154 g->GCdebt -= osize; 154 g->totalbytes -= osize;
155} 155}
156 156
157 157
@@ -181,10 +181,10 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
181 if (l_unlikely(newblock == NULL && nsize > 0)) { 181 if (l_unlikely(newblock == NULL && nsize > 0)) {
182 newblock = tryagain(L, block, osize, nsize); 182 newblock = tryagain(L, block, osize, nsize);
183 if (newblock == NULL) /* still no memory? */ 183 if (newblock == NULL) /* still no memory? */
184 return NULL; /* do not update 'GCdebt' */ 184 return NULL; /* do not update 'totalbytes' */
185 } 185 }
186 lua_assert((nsize == 0) == (newblock == NULL)); 186 lua_assert((nsize == 0) == (newblock == NULL));
187 g->GCdebt = (g->GCdebt + nsize) - osize; 187 g->totalbytes += nsize - osize;
188 return newblock; 188 return newblock;
189} 189}
190 190
@@ -209,7 +209,7 @@ void *luaM_malloc_ (lua_State *L, size_t size, int tag) {
209 if (newblock == NULL) 209 if (newblock == NULL)
210 luaM_error(L); 210 luaM_error(L);
211 } 211 }
212 g->GCdebt += size; 212 g->totalbytes += size;
213 return newblock; 213 return newblock;
214 } 214 }
215} 215}
diff --git a/lmem.h b/lmem.h
index 8c75a44b..c5dada9c 100644
--- a/lmem.h
+++ b/lmem.h
@@ -63,6 +63,8 @@
63 63
64#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag) 64#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag)
65 65
66#define luaM_newblock(L, size) luaM_newvector(L, size, char)
67
66#define luaM_growvector(L,v,nelems,size,t,limit,e) \ 68#define luaM_growvector(L,v,nelems,size,t,limit,e) \
67 ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ 69 ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \
68 luaM_limitN(limit,t),e))) 70 luaM_limitN(limit,t),e)))
diff --git a/lobject.h b/lobject.h
index 342197c4..c6c43647 100644
--- a/lobject.h
+++ b/lobject.h
@@ -394,7 +394,7 @@ typedef struct TString {
394 size_t lnglen; /* length for long strings */ 394 size_t lnglen; /* length for long strings */
395 struct TString *hnext; /* linked list for hash table */ 395 struct TString *hnext; /* linked list for hash table */
396 } u; 396 } u;
397 char contents[1]; 397 char contents[1]; /* string body starts here */
398} TString; 398} TString;
399 399
400 400
@@ -403,15 +403,22 @@ typedef struct TString {
403** Get the actual string (array of bytes) from a 'TString'. (Generic 403** Get the actual string (array of bytes) from a 'TString'. (Generic
404** version and specialized versions for long and short strings.) 404** version and specialized versions for long and short strings.)
405*/ 405*/
406#define getstr(ts) ((ts)->contents)
407#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents) 406#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents)
408#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents) 407#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents)
408#define getstr(ts) ((ts)->contents)
409 409
410 410
411/* get string length from 'TString *s' */ 411/* get string length from 'TString *s' */
412#define tsslen(s) \ 412#define tsslen(s) \
413 ((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen) 413 ((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen)
414 414
415/*
416** Get string and length */
417#define getlstr(ts, len) \
418 ((ts)->shrlen != 0xFF \
419 ? (cast_void(len = (ts)->shrlen), (ts)->contents) \
420 : (cast_void(len = (ts)->u.lnglen), (ts)->contents))
421
415/* }================================================================== */ 422/* }================================================================== */
416 423
417 424
@@ -546,13 +553,21 @@ typedef struct AbsLineInfo {
546 int line; 553 int line;
547} AbsLineInfo; 554} AbsLineInfo;
548 555
556
557/*
558** Flags in Prototypes
559*/
560#define PF_ISVARARG 1
561#define PF_FIXED 2 /* prototype has parts in fixed memory */
562
563
549/* 564/*
550** Function Prototypes 565** Function Prototypes
551*/ 566*/
552typedef struct Proto { 567typedef struct Proto {
553 CommonHeader; 568 CommonHeader;
554 lu_byte numparams; /* number of fixed (named) parameters */ 569 lu_byte numparams; /* number of fixed (named) parameters */
555 lu_byte is_vararg; 570 lu_byte flag;
556 lu_byte maxstacksize; /* number of registers needed by this function */ 571 lu_byte maxstacksize; /* number of registers needed by this function */
557 int sizeupvalues; /* size of 'upvalues' */ 572 int sizeupvalues; /* size of 'upvalues' */
558 int sizek; /* size of 'k' */ 573 int sizek; /* size of 'k' */
@@ -746,7 +761,6 @@ typedef struct Table {
746 unsigned int alimit; /* "limit" of 'array' array */ 761 unsigned int alimit; /* "limit" of 'array' array */
747 ArrayCell *array; /* array part */ 762 ArrayCell *array; /* array part */
748 Node *node; 763 Node *node;
749 Node *lastfree; /* any free position is before this position */
750 struct Table *metatable; 764 struct Table *metatable;
751 GCObject *gclist; 765 GCObject *gclist;
752} Table; 766} Table;
diff --git a/lparser.c b/lparser.c
index 2b888c7c..2a84637a 100644
--- a/lparser.c
+++ b/lparser.c
@@ -187,10 +187,10 @@ static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) {
187 187
188 188
189/* 189/*
190** Create a new local variable with the given 'name'. Return its index 190** Create a new local variable with the given 'name' and given 'kind'.
191** in the function. 191** Return its index in the function.
192*/ 192*/
193static int new_localvar (LexState *ls, TString *name) { 193static int new_localvarkind (LexState *ls, TString *name, int kind) {
194 lua_State *L = ls->L; 194 lua_State *L = ls->L;
195 FuncState *fs = ls->fs; 195 FuncState *fs = ls->fs;
196 Dyndata *dyd = ls->dyd; 196 Dyndata *dyd = ls->dyd;
@@ -200,11 +200,19 @@ static int new_localvar (LexState *ls, TString *name) {
200 luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, 200 luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
201 dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); 201 dyd->actvar.size, Vardesc, USHRT_MAX, "local variables");
202 var = &dyd->actvar.arr[dyd->actvar.n++]; 202 var = &dyd->actvar.arr[dyd->actvar.n++];
203 var->vd.kind = VDKREG; /* default */ 203 var->vd.kind = kind; /* default */
204 var->vd.name = name; 204 var->vd.name = name;
205 return dyd->actvar.n - 1 - fs->firstlocal; 205 return dyd->actvar.n - 1 - fs->firstlocal;
206} 206}
207 207
208
209/*
210** Create a new local variable with the given 'name' and regular kind.
211*/
212static int new_localvar (LexState *ls, TString *name) {
213 return new_localvarkind(ls, name, VDKREG);
214}
215
208#define new_localvarliteral(ls,v) \ 216#define new_localvarliteral(ls,v) \
209 new_localvar(ls, \ 217 new_localvar(ls, \
210 luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); 218 luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1));
@@ -512,7 +520,8 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
512** local variable. 520** local variable.
513*/ 521*/
514static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { 522static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) {
515 const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->vd.name); 523 TString *tsname = getlocalvardesc(ls->fs, gt->nactvar)->vd.name;
524 const char *varname = getstr(tsname);
516 const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'"; 525 const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'";
517 msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); 526 msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname);
518 luaK_semerror(ls, msg); /* raise the error */ 527 luaK_semerror(ls, msg); /* raise the error */
@@ -951,7 +960,7 @@ static void constructor (LexState *ls, expdesc *t) {
951 960
952 961
953static void setvararg (FuncState *fs, int nparams) { 962static void setvararg (FuncState *fs, int nparams) {
954 fs->f->is_vararg = 1; 963 fs->f->flag |= PF_ISVARARG;
955 luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0); 964 luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0);
956} 965}
957 966
@@ -1169,7 +1178,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
1169 } 1178 }
1170 case TK_DOTS: { /* vararg */ 1179 case TK_DOTS: { /* vararg */
1171 FuncState *fs = ls->fs; 1180 FuncState *fs = ls->fs;
1172 check_condition(ls, fs->f->is_vararg, 1181 check_condition(ls, fs->f->flag & PF_ISVARARG,
1173 "cannot use '...' outside a vararg function"); 1182 "cannot use '...' outside a vararg function");
1174 init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1)); 1183 init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1));
1175 break; 1184 break;
@@ -1550,6 +1559,7 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
1550 int prep, endfor; 1559 int prep, endfor;
1551 checknext(ls, TK_DO); 1560 checknext(ls, TK_DO);
1552 prep = luaK_codeABx(fs, forprep[isgen], base, 0); 1561 prep = luaK_codeABx(fs, forprep[isgen], base, 0);
1562 fs->freereg--; /* both 'forprep' remove one register from the stack */
1553 enterblock(fs, &bl, 0); /* scope for declared variables */ 1563 enterblock(fs, &bl, 0); /* scope for declared variables */
1554 adjustlocalvars(ls, nvars); 1564 adjustlocalvars(ls, nvars);
1555 luaK_reserveregs(fs, nvars); 1565 luaK_reserveregs(fs, nvars);
@@ -1572,8 +1582,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1572 int base = fs->freereg; 1582 int base = fs->freereg;
1573 new_localvarliteral(ls, "(for state)"); 1583 new_localvarliteral(ls, "(for state)");
1574 new_localvarliteral(ls, "(for state)"); 1584 new_localvarliteral(ls, "(for state)");
1575 new_localvarliteral(ls, "(for state)"); 1585 new_localvarkind(ls, varname, RDKCONST); /* control variable */
1576 new_localvar(ls, varname);
1577 checknext(ls, '='); 1586 checknext(ls, '=');
1578 exp1(ls); /* initial value */ 1587 exp1(ls); /* initial value */
1579 checknext(ls, ','); 1588 checknext(ls, ',');
@@ -1584,7 +1593,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1584 luaK_int(fs, fs->freereg, 1); 1593 luaK_int(fs, fs->freereg, 1);
1585 luaK_reserveregs(fs, 1); 1594 luaK_reserveregs(fs, 1);
1586 } 1595 }
1587 adjustlocalvars(ls, 3); /* control variables */ 1596 adjustlocalvars(ls, 2); /* start scope for internal variables */
1588 forbody(ls, base, line, 1, 0); 1597 forbody(ls, base, line, 1, 0);
1589} 1598}
1590 1599
@@ -1593,16 +1602,15 @@ static void forlist (LexState *ls, TString *indexname) {
1593 /* forlist -> NAME {,NAME} IN explist forbody */ 1602 /* forlist -> NAME {,NAME} IN explist forbody */
1594 FuncState *fs = ls->fs; 1603 FuncState *fs = ls->fs;
1595 expdesc e; 1604 expdesc e;
1596 int nvars = 5; /* gen, state, control, toclose, 'indexname' */ 1605 int nvars = 4; /* function, state, closing, control */
1597 int line; 1606 int line;
1598 int base = fs->freereg; 1607 int base = fs->freereg;
1599 /* create control variables */ 1608 /* create internal variables */
1600 new_localvarliteral(ls, "(for state)"); 1609 new_localvarliteral(ls, "(for state)"); /* iterator function */
1601 new_localvarliteral(ls, "(for state)"); 1610 new_localvarliteral(ls, "(for state)"); /* state */
1602 new_localvarliteral(ls, "(for state)"); 1611 new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */
1603 new_localvarliteral(ls, "(for state)"); 1612 new_localvarkind(ls, indexname, RDKCONST); /* control variable */
1604 /* create declared variables */ 1613 /* other declared variables */
1605 new_localvar(ls, indexname);
1606 while (testnext(ls, ',')) { 1614 while (testnext(ls, ',')) {
1607 new_localvar(ls, str_checkname(ls)); 1615 new_localvar(ls, str_checkname(ls));
1608 nvars++; 1616 nvars++;
@@ -1610,10 +1618,10 @@ static void forlist (LexState *ls, TString *indexname) {
1610 checknext(ls, TK_IN); 1618 checknext(ls, TK_IN);
1611 line = ls->linenumber; 1619 line = ls->linenumber;
1612 adjust_assign(ls, 4, explist(ls, &e), &e); 1620 adjust_assign(ls, 4, explist(ls, &e), &e);
1613 adjustlocalvars(ls, 4); /* control variables */ 1621 adjustlocalvars(ls, 3); /* start scope for internal variables */
1614 marktobeclosed(fs); /* last control var. must be closed */ 1622 marktobeclosed(fs); /* last internal var. must be closed */
1615 luaK_checkstack(fs, 3); /* extra space to call generator */ 1623 luaK_checkstack(fs, 2); /* extra space to call iterator */
1616 forbody(ls, base, line, nvars - 4, 1); 1624 forbody(ls, base, line, nvars - 3, 1);
1617} 1625}
1618 1626
1619 1627
@@ -1701,7 +1709,8 @@ static void localfunc (LexState *ls) {
1701static int getlocalattribute (LexState *ls) { 1709static int getlocalattribute (LexState *ls) {
1702 /* ATTRIB -> ['<' Name '>'] */ 1710 /* ATTRIB -> ['<' Name '>'] */
1703 if (testnext(ls, '<')) { 1711 if (testnext(ls, '<')) {
1704 const char *attr = getstr(str_checkname(ls)); 1712 TString *ts = str_checkname(ls);
1713 const char *attr = getstr(ts);
1705 checknext(ls, '>'); 1714 checknext(ls, '>');
1706 if (strcmp(attr, "const") == 0) 1715 if (strcmp(attr, "const") == 0)
1707 return RDKCONST; /* read-only variable */ 1716 return RDKCONST; /* read-only variable */
@@ -1728,14 +1737,14 @@ static void localstat (LexState *ls) {
1728 FuncState *fs = ls->fs; 1737 FuncState *fs = ls->fs;
1729 int toclose = -1; /* index of to-be-closed variable (if any) */ 1738 int toclose = -1; /* index of to-be-closed variable (if any) */
1730 Vardesc *var; /* last variable */ 1739 Vardesc *var; /* last variable */
1731 int vidx, kind; /* index and kind of last variable */ 1740 int vidx; /* index of last variable */
1732 int nvars = 0; 1741 int nvars = 0;
1733 int nexps; 1742 int nexps;
1734 expdesc e; 1743 expdesc e;
1735 do { 1744 do {
1736 vidx = new_localvar(ls, str_checkname(ls)); 1745 TString *vname = str_checkname(ls);
1737 kind = getlocalattribute(ls); 1746 int kind = getlocalattribute(ls);
1738 getlocalvardesc(fs, vidx)->vd.kind = kind; 1747 vidx = new_localvarkind(ls, vname, kind);
1739 if (kind == RDKTOCLOSE) { /* to-be-closed? */ 1748 if (kind == RDKTOCLOSE) { /* to-be-closed? */
1740 if (toclose != -1) /* one already present? */ 1749 if (toclose != -1) /* one already present? */
1741 luaK_semerror(ls, "multiple to-be-closed variables in local list"); 1750 luaK_semerror(ls, "multiple to-be-closed variables in local list");
diff --git a/lstate.c b/lstate.c
index 390e9c1a..c01e53ed 100644
--- a/lstate.c
+++ b/lstate.c
@@ -52,46 +52,15 @@ typedef struct LG {
52 52
53 53
54/* 54/*
55** A macro to create a "random" seed when a state is created; 55** set GCdebt to a new value keeping the value (totalobjs + GCdebt)
56** the seed is used to randomize string hashes. 56** invariant (and avoiding underflows in 'totalobjs')
57*/ 57*/
58#if !defined(luai_makeseed) 58void luaE_setdebt (global_State *g, l_obj debt) {
59 59 l_obj tb = gettotalobjs(g);
60#include <time.h>
61
62/*
63** Compute an initial seed with some level of randomness.
64** Rely on Address Space Layout Randomization (if present) and
65** current time.
66*/
67#define addbuff(b,p,e) \
68 { size_t t = cast_sizet(e); \
69 memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
70
71static unsigned int luai_makeseed (lua_State *L) {
72 char buff[3 * sizeof(size_t)];
73 unsigned int h = cast_uint(time(NULL));
74 int p = 0;
75 addbuff(buff, p, L); /* heap variable */
76 addbuff(buff, p, &h); /* local variable */
77 addbuff(buff, p, &lua_newstate); /* public function */
78 lua_assert(p == sizeof(buff));
79 return luaS_hash(buff, p, h);
80}
81
82#endif
83
84
85/*
86** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
87** invariant (and avoiding underflows in 'totalbytes')
88*/
89void luaE_setdebt (global_State *g, l_mem debt) {
90 l_mem tb = gettotalbytes(g);
91 lua_assert(tb > 0); 60 lua_assert(tb > 0);
92 if (debt < tb - MAX_LMEM) 61 if (debt > MAX_LOBJ - tb)
93 debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ 62 debt = MAX_LOBJ - tb; /* will make 'totalobjs == MAX_LMEM' */
94 g->totalbytes = tb - debt; 63 g->totalobjs = tb + debt;
95 g->GCdebt = debt; 64 g->GCdebt = debt;
96} 65}
97 66
@@ -281,7 +250,8 @@ static void close_state (lua_State *L) {
281 } 250 }
282 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); 251 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
283 freestack(L); 252 freestack(L);
284 lua_assert(gettotalbytes(g) == sizeof(LG)); 253 lua_assert(g->totalbytes == sizeof(LG));
254 lua_assert(gettotalobjs(g) == 1);
285 (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ 255 (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
286} 256}
287 257
@@ -352,15 +322,7 @@ LUA_API int lua_closethread (lua_State *L, lua_State *from) {
352} 322}
353 323
354 324
355/* 325LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
356** Deprecated! Use 'lua_closethread' instead.
357*/
358LUA_API int lua_resetthread (lua_State *L) {
359 return lua_closethread(L, NULL);
360}
361
362
363LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
364 int i; 326 int i;
365 lua_State *L; 327 lua_State *L;
366 global_State *g; 328 global_State *g;
@@ -380,7 +342,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
380 g->warnf = NULL; 342 g->warnf = NULL;
381 g->ud_warn = NULL; 343 g->ud_warn = NULL;
382 g->mainthread = L; 344 g->mainthread = L;
383 g->seed = luai_makeseed(L); 345 g->seed = seed;
384 g->gcstp = GCSTPGC; /* no GC while building state */ 346 g->gcstp = GCSTPGC; /* no GC while building state */
385 g->strt.size = g->strt.nuse = 0; 347 g->strt.size = g->strt.nuse = 0;
386 g->strt.hash = NULL; 348 g->strt.hash = NULL;
@@ -398,14 +360,15 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
398 g->weak = g->ephemeron = g->allweak = NULL; 360 g->weak = g->ephemeron = g->allweak = NULL;
399 g->twups = NULL; 361 g->twups = NULL;
400 g->totalbytes = sizeof(LG); 362 g->totalbytes = sizeof(LG);
363 g->totalobjs = 1;
364 g->marked = 0;
401 g->GCdebt = 0; 365 g->GCdebt = 0;
402 g->lastatomic = 0;
403 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ 366 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
404 setgcparam(g->gcpause, LUAI_GCPAUSE); 367 setgcparam(g, gcpause, LUAI_GCPAUSE);
405 setgcparam(g->gcstepmul, LUAI_GCMUL); 368 setgcparam(g, gcstepmul, LUAI_GCMUL);
406 g->gcstepsize = LUAI_GCSTEPSIZE; 369 g->gcstepsize = LUAI_GCSTEPSIZE;
407 setgcparam(g->genmajormul, LUAI_GENMAJORMUL); 370 setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
408 g->genminormul = LUAI_GENMINORMUL; 371 setgcparam(g, genminormul, LUAI_GENMINORMUL);
409 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 372 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
410 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 373 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
411 /* memory allocation error: free partial state */ 374 /* memory allocation error: free partial state */
diff --git a/lstate.h b/lstate.h
index 007704c8..f42db35d 100644
--- a/lstate.h
+++ b/lstate.h
@@ -150,12 +150,13 @@ struct lua_longjmp; /* defined in ldo.c */
150/* kinds of Garbage Collection */ 150/* kinds of Garbage Collection */
151#define KGC_INC 0 /* incremental gc */ 151#define KGC_INC 0 /* incremental gc */
152#define KGC_GEN 1 /* generational gc */ 152#define KGC_GEN 1 /* generational gc */
153#define KGC_GENMAJOR 2 /* generational in "major" mode */
153 154
154 155
155typedef struct stringtable { 156typedef struct stringtable {
156 TString **hash; 157 TString **hash; /* array of buckets (linked lists of strings) */
157 int nuse; /* number of elements */ 158 int nuse; /* number of elements */
158 int size; 159 int size; /* number of buckets */
159} stringtable; 160} stringtable;
160 161
161 162
@@ -254,10 +255,11 @@ struct CallInfo {
254typedef struct global_State { 255typedef struct global_State {
255 lua_Alloc frealloc; /* function to reallocate memory */ 256 lua_Alloc frealloc; /* function to reallocate memory */
256 void *ud; /* auxiliary data to 'frealloc' */ 257 void *ud; /* auxiliary data to 'frealloc' */
257 l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ 258 lu_mem totalbytes; /* number of bytes currently allocated */
258 l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ 259 l_obj totalobjs; /* total number of objects allocated + GCdebt */
259 lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ 260 l_obj GCdebt; /* objects counted but not yet allocated */
260 lu_mem lastatomic; /* see function 'genstep' in file 'lgc.c' */ 261 l_obj marked; /* number of objects marked in a GC cycle */
262 l_obj GClastmajor; /* objects at last major collection */
261 stringtable strt; /* hash table for strings */ 263 stringtable strt; /* hash table for strings */
262 TValue l_registry; 264 TValue l_registry;
263 TValue nilvalue; /* a nil value */ 265 TValue nilvalue; /* a nil value */
@@ -390,10 +392,11 @@ union GCUnion {
390#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc)) 392#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc))
391 393
392 394
393/* actual number of total bytes allocated */ 395/* actual number of total objects allocated */
394#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) 396#define gettotalobjs(g) ((g)->totalobjs - (g)->GCdebt)
395 397
396LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); 398
399LUAI_FUNC void luaE_setdebt (global_State *g, l_obj debt);
397LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); 400LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
398LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); 401LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
399LUAI_FUNC void luaE_shrinkCI (lua_State *L); 402LUAI_FUNC void luaE_shrinkCI (lua_State *L);
diff --git a/lstrlib.c b/lstrlib.c
index 03167161..e29c09b9 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -239,6 +239,7 @@ static int str_dump (lua_State *L) {
239 if (l_unlikely(lua_dump(L, writer, &state, strip) != 0)) 239 if (l_unlikely(lua_dump(L, writer, &state, strip) != 0))
240 return luaL_error(L, "unable to dump given function"); 240 return luaL_error(L, "unable to dump given function");
241 luaL_pushresult(&state.B); 241 luaL_pushresult(&state.B);
242 lua_assert(lua_isfunction(L, 1)); /* lua_dump kept that value */
242 return 1; 243 return 1;
243} 244}
244 245
diff --git a/ltable.c b/ltable.c
index 8c2bc3b2..c9f66b3c 100644
--- a/ltable.c
+++ b/ltable.c
@@ -40,6 +40,27 @@
40 40
41 41
42/* 42/*
43** Only tables with hash parts larget than LIMFORLAST has a 'lastfree'
44** field that optimizes finding a free slot. Smaller tables do a
45** complete search when looking for a free slot.
46*/
47#define LLIMFORLAST 2 /* log2 of LIMTFORLAST */
48#define LIMFORLAST twoto(LLIMFORLAST)
49
50/*
51** Union to store an int field ensuring that what follows it in
52** memory is properly aligned to store a TValue.
53*/
54typedef union {
55 int lastfree;
56 char padding[offsetof(struct { int i; TValue v; }, v)];
57} Limbox;
58
59#define haslastfree(t) ((t)->lsizenode > LLIMFORLAST)
60#define getlastfree(t) (&((cast(Limbox *, (t)->node) - 1)->lastfree))
61
62
63/*
43** MAXABITS is the largest integer such that MAXASIZE fits in an 64** MAXABITS is the largest integer such that MAXASIZE fits in an
44** unsigned int. 65** unsigned int.
45*/ 66*/
@@ -370,8 +391,15 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
370 391
371 392
372static void freehash (lua_State *L, Table *t) { 393static void freehash (lua_State *L, Table *t) {
373 if (!isdummy(t)) 394 if (!isdummy(t)) {
374 luaM_freearray(L, t->node, cast_sizet(sizenode(t))); 395 size_t bsize = sizenode(t) * sizeof(Node); /* 'node' size in bytes */
396 char *arr = cast_charp(t->node);
397 if (haslastfree(t)) {
398 bsize += sizeof(Limbox);
399 arr -= sizeof(Limbox);
400 }
401 luaM_freearray(L, arr, bsize);
402 }
375} 403}
376 404
377 405
@@ -550,7 +578,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
550 if (size == 0) { /* no elements to hash part? */ 578 if (size == 0) { /* no elements to hash part? */
551 t->node = cast(Node *, dummynode); /* use common 'dummynode' */ 579 t->node = cast(Node *, dummynode); /* use common 'dummynode' */
552 t->lsizenode = 0; 580 t->lsizenode = 0;
553 t->lastfree = NULL; /* signal that it is using dummy node */ 581 setdummy(t); /* signal that it is using dummy node */
554 } 582 }
555 else { 583 else {
556 int i; 584 int i;
@@ -558,15 +586,22 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
558 if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) 586 if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE)
559 luaG_runerror(L, "table overflow"); 587 luaG_runerror(L, "table overflow");
560 size = twoto(lsize); 588 size = twoto(lsize);
561 t->node = luaM_newvector(L, size, Node); 589 if (lsize <= LLIMFORLAST) /* no 'lastfree' field? */
590 t->node = luaM_newvector(L, size, Node);
591 else {
592 size_t bsize = size * sizeof(Node) + sizeof(Limbox);
593 char *node = luaM_newblock(L, bsize);
594 t->node = cast(Node *, node + sizeof(Limbox));
595 *getlastfree(t) = size; /* all positions are free */
596 }
597 t->lsizenode = cast_byte(lsize);
598 setnodummy(t);
562 for (i = 0; i < cast_int(size); i++) { 599 for (i = 0; i < cast_int(size); i++) {
563 Node *n = gnode(t, i); 600 Node *n = gnode(t, i);
564 gnext(n) = 0; 601 gnext(n) = 0;
565 setnilkey(n); 602 setnilkey(n);
566 setempty(gval(n)); 603 setempty(gval(n));
567 } 604 }
568 t->lsizenode = cast_byte(lsize);
569 t->lastfree = gnode(t, size); /* all positions are free */
570 } 605 }
571} 606}
572 607
@@ -591,18 +626,21 @@ static void reinsert (lua_State *L, Table *ot, Table *t) {
591 626
592 627
593/* 628/*
594** Exchange the hash part of 't1' and 't2'. 629** Exchange the hash part of 't1' and 't2'. (In 'flags', only the
630** dummy bit must be exchanged: The 'isrealasize' is not related
631** to the hash part, and the metamethod bits do not change during
632** a resize, so the "real" table can keep their values.)
595*/ 633*/
596static void exchangehashpart (Table *t1, Table *t2) { 634static void exchangehashpart (Table *t1, Table *t2) {
597 lu_byte lsizenode = t1->lsizenode; 635 lu_byte lsizenode = t1->lsizenode;
598 Node *node = t1->node; 636 Node *node = t1->node;
599 Node *lastfree = t1->lastfree; 637 int bitdummy1 = t1->flags & BITDUMMY;
600 t1->lsizenode = t2->lsizenode; 638 t1->lsizenode = t2->lsizenode;
601 t1->node = t2->node; 639 t1->node = t2->node;
602 t1->lastfree = t2->lastfree; 640 t1->flags = (t1->flags & NOTBITDUMMY) | (t2->flags & BITDUMMY);
603 t2->lsizenode = lsizenode; 641 t2->lsizenode = lsizenode;
604 t2->node = node; 642 t2->node = node;
605 t2->lastfree = lastfree; 643 t2->flags = (t2->flags & NOTBITDUMMY) | bitdummy1;
606} 644}
607 645
608 646
@@ -626,6 +664,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
626 unsigned int oldasize = setlimittosize(t); 664 unsigned int oldasize = setlimittosize(t);
627 ArrayCell *newarray; 665 ArrayCell *newarray;
628 /* create new hash part with appropriate size into 'newt' */ 666 /* create new hash part with appropriate size into 'newt' */
667 newt.flags = 0;
629 setnodevector(L, &newt, nhsize); 668 setnodevector(L, &newt, nhsize);
630 if (newasize < oldasize) { /* will array shrink? */ 669 if (newasize < oldasize) { /* will array shrink? */
631 t->alimit = newasize; /* pretend array has new size... */ 670 t->alimit = newasize; /* pretend array has new size... */
@@ -717,11 +756,22 @@ void luaH_free (lua_State *L, Table *t) {
717 756
718 757
719static Node *getfreepos (Table *t) { 758static Node *getfreepos (Table *t) {
720 if (!isdummy(t)) { 759 if (haslastfree(t)) { /* does it have 'lastfree' information? */
721 while (t->lastfree > t->node) { 760 /* look for a spot before 'lastfree', updating 'lastfree' */
722 t->lastfree--; 761 while (*getlastfree(t) > 0) {
723 if (keyisnil(t->lastfree)) 762 Node *free = gnode(t, --(*getlastfree(t)));
724 return t->lastfree; 763 if (keyisnil(free))
764 return free;
765 }
766 }
767 else { /* no 'lastfree' information */
768 if (!isdummy(t)) {
769 int i = sizenode(t);
770 while (i--) { /* do a linear search */
771 Node *free = gnode(t, i);
772 if (keyisnil(free))
773 return free;
774 }
725 } 775 }
726 } 776 }
727 return NULL; /* could not find a free place */ 777 return NULL; /* could not find a free place */
diff --git a/ltable.h b/ltable.h
index 1f6d6aa4..210ae7ac 100644
--- a/ltable.h
+++ b/ltable.h
@@ -23,8 +23,18 @@
23#define invalidateTMcache(t) ((t)->flags &= ~maskflags) 23#define invalidateTMcache(t) ((t)->flags &= ~maskflags)
24 24
25 25
26/* true when 't' is using 'dummynode' as its hash part */ 26/*
27#define isdummy(t) ((t)->lastfree == NULL) 27** Bit BITDUMMY set in 'flags' means the table is using the dummy node
28** for its hash part.
29*/
30
31#define BITDUMMY (1 << 6)
32#define NOTBITDUMMY cast_byte(~BITDUMMY)
33#define isdummy(t) ((t)->flags & BITDUMMY)
34
35#define setnodummy(t) ((t)->flags &= NOTBITDUMMY)
36#define setdummy(t) ((t)->flags |= BITDUMMY)
37
28 38
29 39
30/* allocated size for hash nodes */ 40/* allocated size for hash nodes */
diff --git a/ltablib.c b/ltablib.c
index e6bc4d04..44d55ef5 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -230,31 +230,8 @@ typedef unsigned int IdxT;
230** of a partition. (If you don't want/need this "randomness", ~0 is a 230** of a partition. (If you don't want/need this "randomness", ~0 is a
231** good choice.) 231** good choice.)
232*/ 232*/
233#if !defined(l_randomizePivot) /* { */ 233#if !defined(l_randomizePivot)
234 234#define l_randomizePivot(L) luaL_makeseed(L)
235#include <time.h>
236
237/* size of 'e' measured in number of 'unsigned int's */
238#define sof(e) (sizeof(e) / sizeof(unsigned int))
239
240/*
241** Use 'time' and 'clock' as sources of "randomness". Because we don't
242** know the types 'clock_t' and 'time_t', we cannot cast them to
243** anything without risking overflows. A safe way to use their values
244** is to copy them to an array of a known type and use the array values.
245*/
246static unsigned int l_randomizePivot (void) {
247 clock_t c = clock();
248 time_t t = time(NULL);
249 unsigned int buff[sof(c) + sof(t)];
250 unsigned int i, rnd = 0;
251 memcpy(buff, &c, sof(c) * sizeof(unsigned int));
252 memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
253 for (i = 0; i < sof(buff); i++)
254 rnd += buff[i];
255 return rnd;
256}
257
258#endif /* } */ 235#endif /* } */
259 236
260 237
@@ -333,7 +310,7 @@ static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
333*/ 310*/
334static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { 311static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
335 IdxT r4 = (up - lo) / 4; /* range/4 */ 312 IdxT r4 = (up - lo) / 4; /* range/4 */
336 IdxT p = rnd % (r4 * 2) + (lo + r4); 313 IdxT p = (rnd ^ lo ^ up) % (r4 * 2) + (lo + r4);
337 lua_assert(lo + r4 <= p && p <= up - r4); 314 lua_assert(lo + r4 <= p && p <= up - r4);
338 return p; 315 return p;
339} 316}
@@ -391,7 +368,7 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up,
391 up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ 368 up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
392 } 369 }
393 if ((up - lo) / 128 > n) /* partition too imbalanced? */ 370 if ((up - lo) / 128 > n) /* partition too imbalanced? */
394 rnd = l_randomizePivot(); /* try a new randomization */ 371 rnd = l_randomizePivot(L); /* try a new randomization */
395 } /* tail call auxsort(L, lo, up, rnd) */ 372 } /* tail call auxsort(L, lo, up, rnd) */
396} 373}
397 374
diff --git a/ltests.c b/ltests.c
index e2bf76bd..6f556dc9 100644
--- a/ltests.c
+++ b/ltests.c
@@ -297,7 +297,7 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
297 if (isdead(g,t)) return 0; 297 if (isdead(g,t)) return 0;
298 if (issweepphase(g)) 298 if (issweepphase(g))
299 return 1; /* no invariants */ 299 return 1; /* no invariants */
300 else if (g->gckind == KGC_INC) 300 else if (g->gckind != KGC_GEN)
301 return !(isblack(f) && iswhite(t)); /* basic incremental invariant */ 301 return !(isblack(f) && iswhite(t)); /* basic incremental invariant */
302 else { /* generational mode */ 302 else { /* generational mode */
303 if ((getage(f) == G_OLD && isblack(f)) && !isold(t)) 303 if ((getage(f) == G_OLD && isblack(f)) && !isold(t))
@@ -534,7 +534,7 @@ static void checkobject (global_State *g, GCObject *o, int maybedead,
534} 534}
535 535
536 536
537static lu_mem checkgraylist (global_State *g, GCObject *o) { 537static l_obj checkgraylist (global_State *g, GCObject *o) {
538 int total = 0; /* count number of elements in the list */ 538 int total = 0; /* count number of elements in the list */
539 cast_void(g); /* better to keep it if we need to print an object */ 539 cast_void(g); /* better to keep it if we need to print an object */
540 while (o) { 540 while (o) {
@@ -563,7 +563,7 @@ static lu_mem checkgraylist (global_State *g, GCObject *o) {
563/* 563/*
564** Check objects in gray lists. 564** Check objects in gray lists.
565*/ 565*/
566static lu_mem checkgrays (global_State *g) { 566static l_obj checkgrays (global_State *g) {
567 int total = 0; /* count number of elements in all lists */ 567 int total = 0; /* count number of elements in all lists */
568 if (!keepinvariant(g)) return total; 568 if (!keepinvariant(g)) return total;
569 total += checkgraylist(g, g->gray); 569 total += checkgraylist(g, g->gray);
@@ -580,7 +580,7 @@ static lu_mem checkgrays (global_State *g) {
580** 'count' and check its TESTBIT. (It must have been previously set by 580** 'count' and check its TESTBIT. (It must have been previously set by
581** 'checkgraylist'.) 581** 'checkgraylist'.)
582*/ 582*/
583static void incifingray (global_State *g, GCObject *o, lu_mem *count) { 583static void incifingray (global_State *g, GCObject *o, l_obj *count) {
584 if (!keepinvariant(g)) 584 if (!keepinvariant(g))
585 return; /* gray lists not being kept in these phases */ 585 return; /* gray lists not being kept in these phases */
586 if (o->tt == LUA_VUPVAL) { 586 if (o->tt == LUA_VUPVAL) {
@@ -597,10 +597,10 @@ static void incifingray (global_State *g, GCObject *o, lu_mem *count) {
597} 597}
598 598
599 599
600static lu_mem checklist (global_State *g, int maybedead, int tof, 600static l_obj checklist (global_State *g, int maybedead, int tof,
601 GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) { 601 GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) {
602 GCObject *o; 602 GCObject *o;
603 lu_mem total = 0; /* number of object that should be in gray lists */ 603 l_obj total = 0; /* number of object that should be in gray lists */
604 for (o = newl; o != survival; o = o->next) { 604 for (o = newl; o != survival; o = o->next) {
605 checkobject(g, o, maybedead, G_NEW); 605 checkobject(g, o, maybedead, G_NEW);
606 incifingray(g, o, &total); 606 incifingray(g, o, &total);
@@ -629,8 +629,8 @@ int lua_checkmemory (lua_State *L) {
629 global_State *g = G(L); 629 global_State *g = G(L);
630 GCObject *o; 630 GCObject *o;
631 int maybedead; 631 int maybedead;
632 lu_mem totalin; /* total of objects that are in gray lists */ 632 l_obj totalin; /* total of objects that are in gray lists */
633 lu_mem totalshould; /* total of objects that should be in gray lists */ 633 l_obj totalshould; /* total of objects that should be in gray lists */
634 if (keepinvariant(g)) { 634 if (keepinvariant(g)) {
635 assert(!iswhite(g->mainthread)); 635 assert(!iswhite(g->mainthread));
636 assert(!iswhite(gcvalue(&g->l_registry))); 636 assert(!iswhite(gcvalue(&g->l_registry)));
@@ -1002,9 +1002,8 @@ static int table_query (lua_State *L) {
1002 if (i == -1) { 1002 if (i == -1) {
1003 lua_pushinteger(L, asize); 1003 lua_pushinteger(L, asize);
1004 lua_pushinteger(L, allocsizenode(t)); 1004 lua_pushinteger(L, allocsizenode(t));
1005 lua_pushinteger(L, isdummy(t) ? 0 : t->lastfree - t->node);
1006 lua_pushinteger(L, t->alimit); 1005 lua_pushinteger(L, t->alimit);
1007 return 4; 1006 return 3;
1008 } 1007 }
1009 else if ((unsigned int)i < asize) { 1008 else if ((unsigned int)i < asize) {
1010 lua_pushinteger(L, i); 1009 lua_pushinteger(L, i);
@@ -1032,6 +1031,16 @@ static int table_query (lua_State *L) {
1032} 1031}
1033 1032
1034 1033
1034static int query_inc (lua_State *L) {
1035 global_State *g = G(L);
1036 lua_pushinteger(L, gettotalobjs(g));
1037 lua_pushinteger(L, g->GCdebt);
1038 lua_pushinteger(L, applygcparam(g, gcpause, 100));
1039 lua_pushinteger(L, applygcparam(g, gcstepmul, 100));
1040 lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize);
1041 return 5;
1042}
1043
1035static int string_query (lua_State *L) { 1044static int string_query (lua_State *L) {
1036 stringtable *tb = &G(L)->strt; 1045 stringtable *tb = &G(L)->strt;
1037 int s = cast_int(luaL_optinteger(L, 1, 0)) - 1; 1046 int s = cast_int(luaL_optinteger(L, 1, 0)) - 1;
@@ -1154,7 +1163,7 @@ static int num2int (lua_State *L) {
1154static int newstate (lua_State *L) { 1163static int newstate (lua_State *L) {
1155 void *ud; 1164 void *ud;
1156 lua_Alloc f = lua_getallocf(L, &ud); 1165 lua_Alloc f = lua_getallocf(L, &ud);
1157 lua_State *L1 = lua_newstate(f, ud); 1166 lua_State *L1 = lua_newstate(f, ud, 0);
1158 if (L1) { 1167 if (L1) {
1159 lua_atpanic(L1, tpanic); 1168 lua_atpanic(L1, tpanic);
1160 lua_pushlightuserdata(L, L1); 1169 lua_pushlightuserdata(L, L1);
@@ -1173,31 +1182,15 @@ static lua_State *getstate (lua_State *L) {
1173 1182
1174 1183
1175static int loadlib (lua_State *L) { 1184static int loadlib (lua_State *L) {
1176 static const luaL_Reg libs[] = {
1177 {LUA_GNAME, luaopen_base},
1178 {"coroutine", luaopen_coroutine},
1179 {"debug", luaopen_debug},
1180 {"io", luaopen_io},
1181 {"os", luaopen_os},
1182 {"math", luaopen_math},
1183 {"string", luaopen_string},
1184 {"table", luaopen_table},
1185 {"T", luaB_opentests},
1186 {NULL, NULL}
1187 };
1188 lua_State *L1 = getstate(L); 1185 lua_State *L1 = getstate(L);
1189 int i; 1186 int what = luaL_checkinteger(L, 2);
1190 luaL_requiref(L1, "package", luaopen_package, 0); 1187 luaL_openselectedlibs(L1, what);
1188 luaL_requiref(L1, "T", luaB_opentests, 0);
1191 lua_assert(lua_type(L1, -1) == LUA_TTABLE); 1189 lua_assert(lua_type(L1, -1) == LUA_TTABLE);
1192 /* 'requiref' should not reload module already loaded... */ 1190 /* 'requiref' should not reload module already loaded... */
1193 luaL_requiref(L1, "package", NULL, 1); /* seg. fault if it reloads */ 1191 luaL_requiref(L1, "T", NULL, 1); /* seg. fault if it reloads */
1194 /* ...but should return the same module */ 1192 /* ...but should return the same module */
1195 lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ)); 1193 lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ));
1196 luaL_getsubtable(L1, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
1197 for (i = 0; libs[i].name; i++) {
1198 lua_pushcfunction(L1, libs[i].func);
1199 lua_setfield(L1, -2, libs[i].name);
1200 }
1201 return 0; 1194 return 0;
1202} 1195}
1203 1196
@@ -1263,7 +1256,7 @@ static int checkpanic (lua_State *L) {
1263 lua_Alloc f = lua_getallocf(L, &ud); 1256 lua_Alloc f = lua_getallocf(L, &ud);
1264 b.paniccode = luaL_optstring(L, 2, ""); 1257 b.paniccode = luaL_optstring(L, 2, "");
1265 b.L = L; 1258 b.L = L;
1266 L1 = lua_newstate(f, ud); /* create new state */ 1259 L1 = lua_newstate(f, ud, 0); /* create new state */
1267 if (L1 == NULL) { /* error? */ 1260 if (L1 == NULL) { /* error? */
1268 lua_pushnil(L); 1261 lua_pushnil(L);
1269 return 1; 1262 return 1;
@@ -1524,8 +1517,11 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
1524 luaL_loadfile(L1, luaL_checkstring(L1, getnum)); 1517 luaL_loadfile(L1, luaL_checkstring(L1, getnum));
1525 } 1518 }
1526 else if EQ("loadstring") { 1519 else if EQ("loadstring") {
1527 const char *s = luaL_checkstring(L1, getnum); 1520 size_t slen;
1528 luaL_loadstring(L1, s); 1521 const char *s = luaL_checklstring(L1, getnum, &slen);
1522 const char *name = getstring;
1523 const char *mode = getstring;
1524 luaL_loadbufferx(L1, s, slen, name, mode);
1529 } 1525 }
1530 else if EQ("newmetatable") { 1526 else if EQ("newmetatable") {
1531 lua_pushboolean(L1, luaL_newmetatable(L1, getstring)); 1527 lua_pushboolean(L1, luaL_newmetatable(L1, getstring));
@@ -1938,6 +1934,7 @@ static const struct luaL_Reg tests_funcs[] = {
1938 {"pushuserdata", pushuserdata}, 1934 {"pushuserdata", pushuserdata},
1939 {"querystr", string_query}, 1935 {"querystr", string_query},
1940 {"querytab", table_query}, 1936 {"querytab", table_query},
1937 {"queryinc", query_inc},
1941 {"ref", tref}, 1938 {"ref", tref},
1942 {"resume", coresume}, 1939 {"resume", coresume},
1943 {"s2d", s2d}, 1940 {"s2d", s2d},
diff --git a/ltests.h b/ltests.h
index ec520498..da773d6e 100644
--- a/ltests.h
+++ b/ltests.h
@@ -102,9 +102,10 @@ LUA_API void *debug_realloc (void *ud, void *block,
102 size_t osize, size_t nsize); 102 size_t osize, size_t nsize);
103 103
104#if defined(lua_c) 104#if defined(lua_c)
105#define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) 105#define luaL_newstate() \
106#define luaL_openlibs(L) \ 106 lua_newstate(debug_realloc, &l_memcontrol, luaL_makeseed(NULL))
107 { (luaL_openlibs)(L); \ 107#define luai_openlibs(L) \
108 { luaL_openlibs(L); \
108 luaL_requiref(L, "T", luaB_opentests, 1); \ 109 luaL_requiref(L, "T", luaB_opentests, 1); \
109 lua_pop(L, 1); } 110 lua_pop(L, 1); }
110#endif 111#endif
diff --git a/ltm.c b/ltm.c
index fce6245c..c943bc7b 100644
--- a/ltm.c
+++ b/ltm.c
@@ -261,7 +261,7 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
261 int nextra = ci->u.l.nextraargs; 261 int nextra = ci->u.l.nextraargs;
262 if (wanted < 0) { 262 if (wanted < 0) {
263 wanted = nextra; /* get all extra arguments available */ 263 wanted = nextra; /* get all extra arguments available */
264 checkstackGCp(L, nextra, where); /* ensure stack space */ 264 checkstackp(L, nextra, where); /* ensure stack space */
265 L->top.p = where + nextra; /* next instruction will need top */ 265 L->top.p = where + nextra; /* next instruction will need top */
266 } 266 }
267 for (i = 0; i < wanted && i < nextra; i++) 267 for (i = 0; i < wanted && i < nextra; i++)
diff --git a/ltm.h b/ltm.h
index 73b833c6..f3872655 100644
--- a/ltm.h
+++ b/ltm.h
@@ -48,8 +48,8 @@ typedef enum {
48/* 48/*
49** Mask with 1 in all fast-access methods. A 1 in any of these bits 49** Mask with 1 in all fast-access methods. A 1 in any of these bits
50** in the flag of a (meta)table means the metatable does not have the 50** in the flag of a (meta)table means the metatable does not have the
51** corresponding metamethod field. (Bit 7 of the flag is used for 51** corresponding metamethod field. (Bit 6 of the flag indicates that
52** 'isrealasize'.) 52** the table is using the dummy node; bit 7 is used for 'isrealasize'.)
53*/ 53*/
54#define maskflags (~(~0u << (TM_EQ + 1))) 54#define maskflags (~(~0u << (TM_EQ + 1)))
55 55
diff --git a/lua.c b/lua.c
index 3af5ce6a..1e884b07 100644
--- a/lua.c
+++ b/lua.c
@@ -617,6 +617,10 @@ static void doREPL (lua_State *L) {
617 617
618/* }================================================================== */ 618/* }================================================================== */
619 619
620#if !defined(luai_openlibs)
621#define luai_openlibs(L) luaL_openlibs(L)
622#endif
623
620 624
621/* 625/*
622** Main body of stand-alone interpreter (to be called in protected mode). 626** Main body of stand-alone interpreter (to be called in protected mode).
@@ -639,7 +643,7 @@ static int pmain (lua_State *L) {
639 lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ 643 lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
640 lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); 644 lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
641 } 645 }
642 luaL_openlibs(L); /* open standard libraries */ 646 luai_openlibs(L); /* open standard libraries */
643 createargtable(L, argv, argc, script); /* create table 'arg' */ 647 createargtable(L, argv, argc, script); /* create table 'arg' */
644 lua_gc(L, LUA_GCRESTART); /* start GC... */ 648 lua_gc(L, LUA_GCRESTART); /* start GC... */
645 lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ 649 lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */
diff --git a/lua.h b/lua.h
index 040cc8e4..699b7ca7 100644
--- a/lua.h
+++ b/lua.h
@@ -18,8 +18,8 @@
18 18
19 19
20#define LUA_VERSION_MAJOR_N 5 20#define LUA_VERSION_MAJOR_N 5
21#define LUA_VERSION_MINOR_N 4 21#define LUA_VERSION_MINOR_N 5
22#define LUA_VERSION_RELEASE_N 6 22#define LUA_VERSION_RELEASE_N 0
23 23
24#define LUA_VERSION_NUM (LUA_VERSION_MAJOR_N * 100 + LUA_VERSION_MINOR_N) 24#define LUA_VERSION_NUM (LUA_VERSION_MAJOR_N * 100 + LUA_VERSION_MINOR_N)
25#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + LUA_VERSION_RELEASE_N) 25#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + LUA_VERSION_RELEASE_N)
@@ -159,11 +159,11 @@ extern const char lua_ident[];
159/* 159/*
160** state manipulation 160** state manipulation
161*/ 161*/
162LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); 162LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud,
163 unsigned int seed);
163LUA_API void (lua_close) (lua_State *L); 164LUA_API void (lua_close) (lua_State *L);
164LUA_API lua_State *(lua_newthread) (lua_State *L); 165LUA_API lua_State *(lua_newthread) (lua_State *L);
165LUA_API int (lua_closethread) (lua_State *L, lua_State *from); 166LUA_API int (lua_closethread) (lua_State *L, lua_State *from);
166LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */
167 167
168LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); 168LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
169 169
@@ -425,6 +425,8 @@ LUA_API void (lua_closeslot) (lua_State *L, int idx);
425 425
426#define LUA_NUMTAGS LUA_NUMTYPES 426#define LUA_NUMTAGS LUA_NUMTYPES
427 427
428#define lua_resetthread(L) lua_closethread(L,NULL)
429
428/* }============================================================== */ 430/* }============================================================== */
429 431
430/* 432/*
diff --git a/lualib.h b/lualib.h
index 26255290..e124cf1b 100644
--- a/lualib.h
+++ b/lualib.h
@@ -14,39 +14,52 @@
14/* version suffix for environment variable names */ 14/* version suffix for environment variable names */
15#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR 15#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
16 16
17 17#define LUA_GK 1
18LUAMOD_API int (luaopen_base) (lua_State *L); 18LUAMOD_API int (luaopen_base) (lua_State *L);
19 19
20#define LUA_LOADLIBNAME "package"
21#define LUA_LOADLIBK (LUA_GK << 1)
22LUAMOD_API int (luaopen_package) (lua_State *L);
23
24
20#define LUA_COLIBNAME "coroutine" 25#define LUA_COLIBNAME "coroutine"
26#define LUA_COLIBK (LUA_LOADLIBK << 1)
21LUAMOD_API int (luaopen_coroutine) (lua_State *L); 27LUAMOD_API int (luaopen_coroutine) (lua_State *L);
22 28
23#define LUA_TABLIBNAME "table" 29#define LUA_DBLIBNAME "debug"
24LUAMOD_API int (luaopen_table) (lua_State *L); 30#define LUA_DBLIBK (LUA_COLIBK << 1)
31LUAMOD_API int (luaopen_debug) (lua_State *L);
25 32
26#define LUA_IOLIBNAME "io" 33#define LUA_IOLIBNAME "io"
34#define LUA_IOLIBK (LUA_DBLIBK << 1)
27LUAMOD_API int (luaopen_io) (lua_State *L); 35LUAMOD_API int (luaopen_io) (lua_State *L);
28 36
37#define LUA_MATHLIBNAME "math"
38#define LUA_MATHLIBK (LUA_IOLIBK << 1)
39LUAMOD_API int (luaopen_math) (lua_State *L);
40
29#define LUA_OSLIBNAME "os" 41#define LUA_OSLIBNAME "os"
42#define LUA_OSLIBK (LUA_MATHLIBK << 1)
30LUAMOD_API int (luaopen_os) (lua_State *L); 43LUAMOD_API int (luaopen_os) (lua_State *L);
31 44
32#define LUA_STRLIBNAME "string" 45#define LUA_STRLIBNAME "string"
46#define LUA_STRLIBK (LUA_OSLIBK << 1)
33LUAMOD_API int (luaopen_string) (lua_State *L); 47LUAMOD_API int (luaopen_string) (lua_State *L);
34 48
49#define LUA_TABLIBNAME "table"
50#define LUA_TABLIBK (LUA_STRLIBK << 1)
51LUAMOD_API int (luaopen_table) (lua_State *L);
52
35#define LUA_UTF8LIBNAME "utf8" 53#define LUA_UTF8LIBNAME "utf8"
54#define LUA_UTF8LIBK (LUA_TABLIBK << 1)
36LUAMOD_API int (luaopen_utf8) (lua_State *L); 55LUAMOD_API int (luaopen_utf8) (lua_State *L);
37 56
38#define LUA_MATHLIBNAME "math"
39LUAMOD_API int (luaopen_math) (lua_State *L);
40
41#define LUA_DBLIBNAME "debug"
42LUAMOD_API int (luaopen_debug) (lua_State *L);
43
44#define LUA_LOADLIBNAME "package"
45LUAMOD_API int (luaopen_package) (lua_State *L);
46 57
58/* open selected libraries */
59LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int what);
47 60
48/* open all previous libraries */ 61/* open all libraries */
49LUALIB_API void (luaL_openlibs) (lua_State *L); 62#define luaL_openlibs(L) luaL_openselectedlibs(L, ~0)
50 63
51 64
52#endif 65#endif
diff --git a/lundump.c b/lundump.c
index e8d92a85..45708f96 100644
--- a/lundump.c
+++ b/lundump.c
@@ -21,6 +21,7 @@
21#include "lmem.h" 21#include "lmem.h"
22#include "lobject.h" 22#include "lobject.h"
23#include "lstring.h" 23#include "lstring.h"
24#include "ltable.h"
24#include "lundump.h" 25#include "lundump.h"
25#include "lzio.h" 26#include "lzio.h"
26 27
@@ -34,6 +35,10 @@ typedef struct {
34 lua_State *L; 35 lua_State *L;
35 ZIO *Z; 36 ZIO *Z;
36 const char *name; 37 const char *name;
38 Table *h; /* list for string reuse */
39 lu_mem offset; /* current position relative to beginning of dump */
40 lua_Integer nstr; /* number of strings in the list */
41 lu_byte fixed; /* dump is fixed in memory */
37} LoadState; 42} LoadState;
38 43
39 44
@@ -52,6 +57,27 @@ static l_noret error (LoadState *S, const char *why) {
52static void loadBlock (LoadState *S, void *b, size_t size) { 57static void loadBlock (LoadState *S, void *b, size_t size) {
53 if (luaZ_read(S->Z, b, size) != 0) 58 if (luaZ_read(S->Z, b, size) != 0)
54 error(S, "truncated chunk"); 59 error(S, "truncated chunk");
60 S->offset += size;
61}
62
63
64static void loadAlign (LoadState *S, int align) {
65 int padding = align - (S->offset % align);
66 if (padding < align) { /* apd == align means no padding */
67 lua_Integer paddingContent;
68 loadBlock(S, &paddingContent, padding);
69 lua_assert(S->offset % align == 0);
70 }
71}
72
73
74#define getaddr(S,n,t) cast(t *, getaddr_(S,n,sizeof(t)))
75
76static const void *getaddr_ (LoadState *S, int n, int sz) {
77 const void *block = luaZ_getaddr(S->Z, n * sz);
78 if (block == NULL)
79 error(S, "truncated fixed buffer");
80 return block;
55} 81}
56 82
57 83
@@ -62,6 +88,7 @@ static lu_byte loadByte (LoadState *S) {
62 int b = zgetc(S->Z); 88 int b = zgetc(S->Z);
63 if (b == EOZ) 89 if (b == EOZ)
64 error(S, "truncated chunk"); 90 error(S, "truncated chunk");
91 S->offset++;
65 return cast_byte(b); 92 return cast_byte(b);
66} 93}
67 94
@@ -110,10 +137,16 @@ static lua_Integer loadInteger (LoadState *S) {
110static TString *loadStringN (LoadState *S, Proto *p) { 137static TString *loadStringN (LoadState *S, Proto *p) {
111 lua_State *L = S->L; 138 lua_State *L = S->L;
112 TString *ts; 139 TString *ts;
140 TValue sv;
113 size_t size = loadSize(S); 141 size_t size = loadSize(S);
114 if (size == 0) /* no string? */ 142 if (size == 0) /* no string? */
115 return NULL; 143 return NULL;
116 else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ 144 else if (size == 1) { /* previously saved string? */
145 int idx = loadInt(S); /* get its index */
146 const TValue *stv = luaH_getint(S->h, idx);
147 return tsvalue(stv);
148 }
149 else if (size -= 2, size <= LUAI_MAXSHORTLEN) { /* short string? */
117 char buff[LUAI_MAXSHORTLEN]; 150 char buff[LUAI_MAXSHORTLEN];
118 loadVector(S, buff, size); /* load string into buffer */ 151 loadVector(S, buff, size); /* load string into buffer */
119 ts = luaS_newlstr(L, buff, size); /* create string */ 152 ts = luaS_newlstr(L, buff, size); /* create string */
@@ -126,6 +159,10 @@ static TString *loadStringN (LoadState *S, Proto *p) {
126 L->top.p--; /* pop string */ 159 L->top.p--; /* pop string */
127 } 160 }
128 luaC_objbarrier(L, p, ts); 161 luaC_objbarrier(L, p, ts);
162 S->nstr++; /* add string to list of saved strings */
163 setsvalue(L, &sv, ts);
164 luaH_setint(L, S->h, S->nstr, &sv);
165 luaC_objbarrierback(L, obj2gco(S->h), ts);
129 return ts; 166 return ts;
130} 167}
131 168
@@ -143,13 +180,20 @@ static TString *loadString (LoadState *S, Proto *p) {
143 180
144static void loadCode (LoadState *S, Proto *f) { 181static void loadCode (LoadState *S, Proto *f) {
145 int n = loadInt(S); 182 int n = loadInt(S);
146 f->code = luaM_newvectorchecked(S->L, n, Instruction); 183 loadAlign(S, sizeof(f->code[0]));
147 f->sizecode = n; 184 if (S->fixed) {
148 loadVector(S, f->code, n); 185 f->code = getaddr(S, n, Instruction);
186 f->sizecode = n;
187 }
188 else {
189 f->code = luaM_newvectorchecked(S->L, n, Instruction);
190 f->sizecode = n;
191 loadVector(S, f->code, n);
192 }
149} 193}
150 194
151 195
152static void loadFunction(LoadState *S, Proto *f, TString *psource); 196static void loadFunction(LoadState *S, Proto *f);
153 197
154 198
155static void loadConstants (LoadState *S, Proto *f) { 199static void loadConstants (LoadState *S, Proto *f) {
@@ -198,7 +242,7 @@ static void loadProtos (LoadState *S, Proto *f) {
198 for (i = 0; i < n; i++) { 242 for (i = 0; i < n; i++) {
199 f->p[i] = luaF_newproto(S->L); 243 f->p[i] = luaF_newproto(S->L);
200 luaC_objbarrier(S->L, f, f->p[i]); 244 luaC_objbarrier(S->L, f, f->p[i]);
201 loadFunction(S, f->p[i], f->source); 245 loadFunction(S, f->p[i]);
202 } 246 }
203} 247}
204 248
@@ -227,9 +271,15 @@ static void loadUpvalues (LoadState *S, Proto *f) {
227static void loadDebug (LoadState *S, Proto *f) { 271static void loadDebug (LoadState *S, Proto *f) {
228 int i, n; 272 int i, n;
229 n = loadInt(S); 273 n = loadInt(S);
230 f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); 274 if (S->fixed) {
231 f->sizelineinfo = n; 275 f->lineinfo = getaddr(S, n, ls_byte);
232 loadVector(S, f->lineinfo, n); 276 f->sizelineinfo = n;
277 }
278 else {
279 f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte);
280 f->sizelineinfo = n;
281 loadVector(S, f->lineinfo, n);
282 }
233 n = loadInt(S); 283 n = loadInt(S);
234 f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); 284 f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
235 f->sizeabslineinfo = n; 285 f->sizeabslineinfo = n;
@@ -255,14 +305,14 @@ static void loadDebug (LoadState *S, Proto *f) {
255} 305}
256 306
257 307
258static void loadFunction (LoadState *S, Proto *f, TString *psource) { 308static void loadFunction (LoadState *S, Proto *f) {
259 f->source = loadStringN(S, f); 309 f->source = loadStringN(S, f);
260 if (f->source == NULL) /* no source in dump? */
261 f->source = psource; /* reuse parent's source */
262 f->linedefined = loadInt(S); 310 f->linedefined = loadInt(S);
263 f->lastlinedefined = loadInt(S); 311 f->lastlinedefined = loadInt(S);
264 f->numparams = loadByte(S); 312 f->numparams = loadByte(S);
265 f->is_vararg = loadByte(S); 313 f->flag = loadByte(S) & PF_ISVARARG; /* get only the meaningful flags */
314 if (S->fixed)
315 f->flag |= PF_FIXED; /* signal that code is fixed */
266 f->maxstacksize = loadByte(S); 316 f->maxstacksize = loadByte(S);
267 loadCode(S, f); 317 loadCode(S, f);
268 loadConstants(S, f); 318 loadConstants(S, f);
@@ -310,7 +360,7 @@ static void checkHeader (LoadState *S) {
310/* 360/*
311** Load precompiled chunk. 361** Load precompiled chunk.
312*/ 362*/
313LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { 363LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) {
314 LoadState S; 364 LoadState S;
315 LClosure *cl; 365 LClosure *cl;
316 if (*name == '@' || *name == '=') 366 if (*name == '@' || *name == '=')
@@ -321,15 +371,22 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
321 S.name = name; 371 S.name = name;
322 S.L = L; 372 S.L = L;
323 S.Z = Z; 373 S.Z = Z;
374 S.fixed = fixed;
375 S.offset = 1; /* fist byte was already read */
324 checkHeader(&S); 376 checkHeader(&S);
325 cl = luaF_newLclosure(L, loadByte(&S)); 377 cl = luaF_newLclosure(L, loadByte(&S));
326 setclLvalue2s(L, L->top.p, cl); 378 setclLvalue2s(L, L->top.p, cl);
327 luaD_inctop(L); 379 luaD_inctop(L);
380 S.h = luaH_new(L); /* create list of saved strings */
381 S.nstr = 0;
382 sethvalue2s(L, L->top.p, S.h); /* anchor it */
383 luaD_inctop(L);
328 cl->p = luaF_newproto(L); 384 cl->p = luaF_newproto(L);
329 luaC_objbarrier(L, cl, cl->p); 385 luaC_objbarrier(L, cl, cl->p);
330 loadFunction(&S, cl->p, NULL); 386 loadFunction(&S, cl->p);
331 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 387 lua_assert(cl->nupvalues == cl->p->sizeupvalues);
332 luai_verifycode(L, cl->p); 388 luai_verifycode(L, cl->p);
389 L->top.p--; /* pop table */
333 return cl; 390 return cl;
334} 391}
335 392
diff --git a/lundump.h b/lundump.h
index bc71ced8..05ac7f85 100644
--- a/lundump.h
+++ b/lundump.h
@@ -26,10 +26,11 @@
26#define LUAC_FORMAT 0 /* this is the official format */ 26#define LUAC_FORMAT 0 /* this is the official format */
27 27
28/* load one chunk; from lundump.c */ 28/* load one chunk; from lundump.c */
29LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); 29LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name,
30 int fixed);
30 31
31/* dump one chunk; from ldump.c */ 32/* dump one chunk; from ldump.c */
32LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 33LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
33 void* data, int strip); 34 void* data, int strip, Table *h);
34 35
35#endif 36#endif
diff --git a/lvm.c b/lvm.c
index 9b71ff31..e4c026fd 100644
--- a/lvm.c
+++ b/lvm.c
@@ -93,7 +93,9 @@ static int l_strton (const TValue *obj, TValue *result) {
93 return 0; 93 return 0;
94 else { 94 else {
95 TString *st = tsvalue(obj); 95 TString *st = tsvalue(obj);
96 return (luaO_str2num(getstr(st), result) == tsslen(st) + 1); 96 size_t stlen;
97 const char *s = getlstr(st, stlen);
98 return (luaO_str2num(s, result) == stlen + 1);
97 } 99 }
98} 100}
99 101
@@ -198,12 +200,15 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
198 200
199/* 201/*
200** Prepare a numerical for loop (opcode OP_FORPREP). 202** Prepare a numerical for loop (opcode OP_FORPREP).
203** Before execution, stack is as follows:
204** ra : initial value
205** ra + 1 : limit
206** ra + 2 : step
201** Return true to skip the loop. Otherwise, 207** Return true to skip the loop. Otherwise,
202** after preparation, stack will be as follows: 208** after preparation, stack will be as follows:
203** ra : internal index (safe copy of the control variable) 209** ra : loop counter (integer loops) or limit (float loops)
204** ra + 1 : loop counter (integer loops) or limit (float loops) 210** ra + 1 : step
205** ra + 2 : step 211** ra + 2 : control variable
206** ra + 3 : control variable
207*/ 212*/
208static int forprep (lua_State *L, StkId ra) { 213static int forprep (lua_State *L, StkId ra) {
209 TValue *pinit = s2v(ra); 214 TValue *pinit = s2v(ra);
@@ -215,7 +220,6 @@ static int forprep (lua_State *L, StkId ra) {
215 lua_Integer limit; 220 lua_Integer limit;
216 if (step == 0) 221 if (step == 0)
217 luaG_runerror(L, "'for' step is zero"); 222 luaG_runerror(L, "'for' step is zero");
218 setivalue(s2v(ra + 3), init); /* control variable */
219 if (forlimit(L, init, plimit, &limit, step)) 223 if (forlimit(L, init, plimit, &limit, step))
220 return 1; /* skip the loop */ 224 return 1; /* skip the loop */
221 else { /* prepare loop counter */ 225 else { /* prepare loop counter */
@@ -230,9 +234,10 @@ static int forprep (lua_State *L, StkId ra) {
230 /* 'step+1' avoids negating 'mininteger' */ 234 /* 'step+1' avoids negating 'mininteger' */
231 count /= l_castS2U(-(step + 1)) + 1u; 235 count /= l_castS2U(-(step + 1)) + 1u;
232 } 236 }
233 /* store the counter in place of the limit (which won't be 237 /* use 'chgivalue' for places that for sure had integers */
234 needed anymore) */ 238 chgivalue(s2v(ra), l_castU2S(count)); /* change init to count */
235 setivalue(plimit, l_castU2S(count)); 239 setivalue(s2v(ra + 1), step); /* change limit to step */
240 chgivalue(s2v(ra + 2), init); /* change step to init */
236 } 241 }
237 } 242 }
238 else { /* try making all values floats */ 243 else { /* try making all values floats */
@@ -249,11 +254,10 @@ static int forprep (lua_State *L, StkId ra) {
249 : luai_numlt(init, limit)) 254 : luai_numlt(init, limit))
250 return 1; /* skip the loop */ 255 return 1; /* skip the loop */
251 else { 256 else {
252 /* make sure internal values are all floats */ 257 /* make sure all values are floats */
253 setfltvalue(plimit, limit); 258 setfltvalue(s2v(ra), limit);
254 setfltvalue(pstep, step); 259 setfltvalue(s2v(ra + 1), step);
255 setfltvalue(s2v(ra), init); /* internal index */ 260 setfltvalue(s2v(ra + 2), init); /* control variable */
256 setfltvalue(s2v(ra + 3), init); /* control variable */
257 } 261 }
258 } 262 }
259 return 0; 263 return 0;
@@ -266,14 +270,13 @@ static int forprep (lua_State *L, StkId ra) {
266** written online with opcode OP_FORLOOP, for performance.) 270** written online with opcode OP_FORLOOP, for performance.)
267*/ 271*/
268static int floatforloop (StkId ra) { 272static int floatforloop (StkId ra) {
269 lua_Number step = fltvalue(s2v(ra + 2)); 273 lua_Number step = fltvalue(s2v(ra + 1));
270 lua_Number limit = fltvalue(s2v(ra + 1)); 274 lua_Number limit = fltvalue(s2v(ra));
271 lua_Number idx = fltvalue(s2v(ra)); /* internal index */ 275 lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */
272 idx = luai_numadd(L, idx, step); /* increment index */ 276 idx = luai_numadd(L, idx, step); /* increment index */
273 if (luai_numlt(0, step) ? luai_numle(idx, limit) 277 if (luai_numlt(0, step) ? luai_numle(idx, limit)
274 : luai_numle(limit, idx)) { 278 : luai_numle(limit, idx)) {
275 chgfltvalue(s2v(ra), idx); /* update internal index */ 279 chgfltvalue(s2v(ra + 2), idx); /* update control variable */
276 setfltvalue(s2v(ra + 3), idx); /* and control variable */
277 return 1; /* jump back */ 280 return 1; /* jump back */
278 } 281 }
279 else 282 else
@@ -366,10 +369,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
366** have different lengths. 369** have different lengths.
367*/ 370*/
368static int l_strcmp (const TString *ts1, const TString *ts2) { 371static int l_strcmp (const TString *ts1, const TString *ts2) {
369 const char *s1 = getstr(ts1); 372 size_t rl1; /* real length */
370 size_t rl1 = tsslen(ts1); /* real length */ 373 const char *s1 = getlstr(ts1, rl1);
371 const char *s2 = getstr(ts2); 374 size_t rl2;
372 size_t rl2 = tsslen(ts2); 375 const char *s2 = getlstr(ts2, rl2);
373 for (;;) { /* for each segment */ 376 for (;;) { /* for each segment */
374 int temp = strcoll(s1, s2); 377 int temp = strcoll(s1, s2);
375 if (temp != 0) /* not equal? */ 378 if (temp != 0) /* not equal? */
@@ -619,8 +622,9 @@ static void copy2buff (StkId top, int n, char *buff) {
619 size_t tl = 0; /* size already copied */ 622 size_t tl = 0; /* size already copied */
620 do { 623 do {
621 TString *st = tsvalue(s2v(top - n)); 624 TString *st = tsvalue(s2v(top - n));
622 size_t l = tsslen(st); /* length of string being copied */ 625 size_t l; /* length of string being copied */
623 memcpy(buff + tl, getstr(st), l * sizeof(char)); 626 const char *s = getlstr(st, l);
627 memcpy(buff + tl, s, l * sizeof(char));
624 tl += l; 628 tl += l;
625 } while (--n > 0); 629 } while (--n > 0);
626} 630}
@@ -1766,15 +1770,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1766 } 1770 }
1767 vmcase(OP_FORLOOP) { 1771 vmcase(OP_FORLOOP) {
1768 StkId ra = RA(i); 1772 StkId ra = RA(i);
1769 if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ 1773 if (ttisinteger(s2v(ra + 1))) { /* integer loop? */
1770 lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); 1774 lua_Unsigned count = l_castS2U(ivalue(s2v(ra)));
1771 if (count > 0) { /* still more iterations? */ 1775 if (count > 0) { /* still more iterations? */
1772 lua_Integer step = ivalue(s2v(ra + 2)); 1776 lua_Integer step = ivalue(s2v(ra + 1));
1773 lua_Integer idx = ivalue(s2v(ra)); /* internal index */ 1777 lua_Integer idx = ivalue(s2v(ra + 2)); /* control variable */
1774 chgivalue(s2v(ra + 1), count - 1); /* update counter */ 1778 chgivalue(s2v(ra), count - 1); /* update counter */
1775 idx = intop(+, idx, step); /* add step to index */ 1779 idx = intop(+, idx, step); /* add step to index */
1776 chgivalue(s2v(ra), idx); /* update internal index */ 1780 chgivalue(s2v(ra + 2), idx); /* update control variable */
1777 setivalue(s2v(ra + 3), idx); /* and control variable */
1778 pc -= GETARG_Bx(i); /* jump back */ 1781 pc -= GETARG_Bx(i); /* jump back */
1779 } 1782 }
1780 } 1783 }
@@ -1791,26 +1794,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1791 vmbreak; 1794 vmbreak;
1792 } 1795 }
1793 vmcase(OP_TFORPREP) { 1796 vmcase(OP_TFORPREP) {
1797 /* before: 'ra' has the iterator function, 'ra + 1' has the state,
1798 'ra + 2' has the initial value for the control variable, and
1799 'ra + 3' has the closing variable. This opcode then swaps the
1800 control and the closing variables and marks the closing variable
1801 as to-be-closed.
1802 */
1794 StkId ra = RA(i); 1803 StkId ra = RA(i);
1795 /* create to-be-closed upvalue (if needed) */ 1804 TValue temp; /* to swap control and closing variables */
1796 halfProtect(luaF_newtbcupval(L, ra + 3)); 1805 setobj(L, &temp, s2v(ra + 3));
1797 pc += GETARG_Bx(i); 1806 setobjs2s(L, ra + 3, ra + 2);
1798 i = *(pc++); /* go to next instruction */ 1807 setobj2s(L, ra + 2, &temp);
1808 /* create to-be-closed upvalue (if closing var. is not nil) */
1809 halfProtect(luaF_newtbcupval(L, ra + 2));
1810 pc += GETARG_Bx(i); /* go to end of the loop */
1811 i = *(pc++); /* fetch next instruction */
1799 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); 1812 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
1800 goto l_tforcall; 1813 goto l_tforcall;
1801 } 1814 }
1802 vmcase(OP_TFORCALL) { 1815 vmcase(OP_TFORCALL) {
1803 l_tforcall: { 1816 l_tforcall: {
1804 StkId ra = RA(i);
1805 /* 'ra' has the iterator function, 'ra + 1' has the state, 1817 /* 'ra' has the iterator function, 'ra + 1' has the state,
1806 'ra + 2' has the control variable, and 'ra + 3' has the 1818 'ra + 2' has the closing variable, and 'ra + 3' has the control
1807 to-be-closed variable. The call will use the stack after 1819 variable. The call will use the stack starting at 'ra + 3',
1808 these values (starting at 'ra + 4') 1820 so that it preserves the first three values, and the first
1821 return will be the new value for the control variable.
1809 */ 1822 */
1810 /* push function, state, and control variable */ 1823 StkId ra = RA(i);
1811 memcpy(ra + 4, ra, 3 * sizeof(*ra)); 1824 setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */
1812 L->top.p = ra + 4 + 3; 1825 setobjs2s(L, ra + 4, ra + 1); /* copy state */
1813 ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ 1826 setobjs2s(L, ra + 3, ra); /* copy function */
1827 L->top.p = ra + 3 + 3;
1828 ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */
1814 updatestack(ci); /* stack may have changed */ 1829 updatestack(ci); /* stack may have changed */
1815 i = *(pc++); /* go to next instruction */ 1830 i = *(pc++); /* go to next instruction */
1816 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); 1831 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
@@ -1819,10 +1834,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1819 vmcase(OP_TFORLOOP) { 1834 vmcase(OP_TFORLOOP) {
1820 l_tforloop: { 1835 l_tforloop: {
1821 StkId ra = RA(i); 1836 StkId ra = RA(i);
1822 if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ 1837 if (!ttisnil(s2v(ra + 3))) /* continue loop? */
1823 setobjs2s(L, ra + 2, ra + 4); /* save control variable */
1824 pc -= GETARG_Bx(i); /* jump back */ 1838 pc -= GETARG_Bx(i); /* jump back */
1825 }
1826 vmbreak; 1839 vmbreak;
1827 }} 1840 }}
1828 vmcase(OP_SETLIST) { 1841 vmcase(OP_SETLIST) {
diff --git a/lzio.c b/lzio.c
index cd0a02d5..78f7ac83 100644
--- a/lzio.c
+++ b/lzio.c
@@ -45,17 +45,25 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
45 45
46 46
47/* --------------------------------------------------------------- read --- */ 47/* --------------------------------------------------------------- read --- */
48
49static int checkbuffer (ZIO *z) {
50 if (z->n == 0) { /* no bytes in buffer? */
51 if (luaZ_fill(z) == EOZ) /* try to read more */
52 return 0; /* no more input */
53 else {
54 z->n++; /* luaZ_fill consumed first byte; put it back */
55 z->p--;
56 }
57 }
58 return 1; /* now buffer has something */
59}
60
61
48size_t luaZ_read (ZIO *z, void *b, size_t n) { 62size_t luaZ_read (ZIO *z, void *b, size_t n) {
49 while (n) { 63 while (n) {
50 size_t m; 64 size_t m;
51 if (z->n == 0) { /* no bytes in buffer? */ 65 if (!checkbuffer(z))
52 if (luaZ_fill(z) == EOZ) /* try to read more */ 66 return n; /* no more input; return number of missing bytes */
53 return n; /* no more input; return number of missing bytes */
54 else {
55 z->n++; /* luaZ_fill consumed first byte; put it back */
56 z->p--;
57 }
58 }
59 m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ 67 m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
60 memcpy(b, z->p, m); 68 memcpy(b, z->p, m);
61 z->n -= m; 69 z->n -= m;
@@ -66,3 +74,15 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
66 return 0; 74 return 0;
67} 75}
68 76
77
78const void *luaZ_getaddr (ZIO* z, size_t n) {
79 const void *res;
80 if (!checkbuffer(z))
81 return NULL; /* no more input */
82 if (z->n < n) /* not enough bytes? */
83 return NULL; /* block not whole; cannot give an address */
84 res = z->p; /* get block address */
85 z->n -= n; /* consume these bytes */
86 z->p += n;
87 return res;
88}
diff --git a/lzio.h b/lzio.h
index 38f397fd..55cc74ad 100644
--- a/lzio.h
+++ b/lzio.h
@@ -48,6 +48,7 @@ LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
48 void *data); 48 void *data);
49LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ 49LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */
50 50
51LUAI_FUNC const void *luaZ_getaddr (ZIO* z, size_t n);
51 52
52 53
53/* --------- Private Part ------------------ */ 54/* --------- Private Part ------------------ */
diff --git a/manual/manual.of b/manual/manual.of
index ad120f5e..3eab69fa 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -1467,7 +1467,7 @@ It has the following syntax:
1467 exp @bnfter{,} exp @bnfopt{@bnfter{,} exp} @Rw{do} block @Rw{end}} 1467 exp @bnfter{,} exp @bnfopt{@bnfter{,} exp} @Rw{do} block @Rw{end}}
1468} 1468}
1469The given identifier (@bnfNter{Name}) defines the control variable, 1469The given identifier (@bnfNter{Name}) defines the control variable,
1470which is a new variable local to the loop body (@emph{block}). 1470which is a new read-only variable local to the loop body (@emph{block}).
1471 1471
1472The loop starts by evaluating once the three control expressions. 1472The loop starts by evaluating once the three control expressions.
1473Their values are called respectively 1473Their values are called respectively
@@ -1499,11 +1499,6 @@ For integer loops,
1499the control variable never wraps around; 1499the control variable never wraps around;
1500instead, the loop ends in case of an overflow. 1500instead, the loop ends in case of an overflow.
1501 1501
1502You should not change the value of the control variable
1503during the loop.
1504If you need its value after the loop,
1505assign it to another variable before exiting the loop.
1506
1507} 1502}
1508 1503
1509@sect4{@title{The generic @Rw{for} loop} 1504@sect4{@title{The generic @Rw{for} loop}
@@ -1526,7 +1521,8 @@ for @rep{var_1}, @Cdots, @rep{var_n} in @rep{explist} do @rep{body} end
1526works as follows. 1521works as follows.
1527 1522
1528The names @rep{var_i} declare loop variables local to the loop body. 1523The names @rep{var_i} declare loop variables local to the loop body.
1529The first of these variables is the @emph{control variable}. 1524The first of these variables is the @emph{control variable},
1525which is a read-only variable.
1530 1526
1531The loop starts by evaluating @rep{explist} 1527The loop starts by evaluating @rep{explist}
1532to produce four values: 1528to produce four values:
@@ -1550,9 +1546,6 @@ to-be-closed variable @see{to-be-closed},
1550which can be used to release resources when the loop ends. 1546which can be used to release resources when the loop ends.
1551Otherwise, it does not interfere with the loop. 1547Otherwise, it does not interfere with the loop.
1552 1548
1553You should not change the value of the control variable
1554during the loop.
1555
1556} 1549}
1557 1550
1558} 1551}
@@ -1586,7 +1579,8 @@ Each variable name may be postfixed by an attribute
1586@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}} 1579@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}}
1587} 1580}
1588There are two possible attributes: 1581There are two possible attributes:
1589@id{const}, which declares a @x{constant variable}, 1582@id{const}, which declares a @emph{constant} or @emph{read-only} variable,
1583@index{constant variable}
1590that is, a variable that cannot be assigned to 1584that is, a variable that cannot be assigned to
1591after its initialization; 1585after its initialization;
1592and @id{close}, which declares a to-be-closed variable @see{to-be-closed}. 1586and @id{close}, which declares a to-be-closed variable @see{to-be-closed}.
@@ -2736,7 +2730,8 @@ For such errors, Lua does not call the @x{message handler}.
2736 2730
2737@item{@defid{LUA_ERRERR}| error while running the @x{message handler}.} 2731@item{@defid{LUA_ERRERR}| error while running the @x{message handler}.}
2738 2732
2739@item{@defid{LUA_ERRSYNTAX}| syntax error during precompilation.} 2733@item{@defid{LUA_ERRSYNTAX}| syntax error during precompilation
2734or format error in a binary chunk.}
2740 2735
2741@item{@defid{LUA_YIELD}| the thread (coroutine) yields.} 2736@item{@defid{LUA_YIELD}| the thread (coroutine) yields.}
2742 2737
@@ -3652,6 +3647,18 @@ and loads it accordingly (see program @idx{luac}).
3652The string @id{mode} works as in function @Lid{load}, 3647The string @id{mode} works as in function @Lid{load},
3653with the addition that 3648with the addition that
3654a @id{NULL} value is equivalent to the string @St{bt}. 3649a @id{NULL} value is equivalent to the string @St{bt}.
3650Moreover, it may have a @Char{B} instead of a @Char{b},
3651meaning a @emphx{fixed buffer} with the binary dump.
3652
3653A fixed buffer means that the address returned by the reader function
3654should contain the chunk until everything created by the chunk has
3655been collected.
3656(In general, a fixed buffer would keep the chunk
3657as its contents until the end of the program,
3658for instance with the chunk in ROM.)
3659Moreover, for a fixed buffer,
3660the reader function should return the entire chunk in the first read.
3661(As an example, @Lid{luaL_loadbufferx} does that.)
3655 3662
3656@id{lua_load} uses the stack internally, 3663@id{lua_load} uses the stack internally,
3657so the reader function must always leave the stack 3664so the reader function must always leave the stack
@@ -3671,7 +3678,8 @@ Other upvalues are initialized with @nil.
3671 3678
3672} 3679}
3673 3680
3674@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud);| 3681@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud,
3682 unsigned int seed);|
3675@apii{0,0,-} 3683@apii{0,0,-}
3676 3684
3677Creates a new independent state and returns its main thread. 3685Creates a new independent state and returns its main thread.
@@ -3682,6 +3690,8 @@ Lua will do all memory allocation for this state
3682through this function @seeF{lua_Alloc}. 3690through this function @seeF{lua_Alloc}.
3683The second argument, @id{ud}, is an opaque pointer that Lua 3691The second argument, @id{ud}, is an opaque pointer that Lua
3684passes to the allocator in every call. 3692passes to the allocator in every call.
3693The third argument, @id{seed}, is a seed for the hashing of
3694strings when they are used as table keys.
3685 3695
3686} 3696}
3687 3697
@@ -5691,6 +5701,8 @@ This function returns the same results as @Lid{lua_load}.
5691@id{name} is the chunk name, 5701@id{name} is the chunk name,
5692used for debug information and error messages. 5702used for debug information and error messages.
5693The string @id{mode} works as in the function @Lid{lua_load}. 5703The string @id{mode} works as in the function @Lid{lua_load}.
5704In particular, this function supports mode @Char{B} for
5705fixed buffers.
5694 5706
5695} 5707}
5696 5708
@@ -5737,6 +5749,16 @@ it does not run it.
5737 5749
5738} 5750}
5739 5751
5752@APIEntry{unsigned int luaL_makeseed (lua_State *L);|
5753@apii{0,0,-}
5754
5755Returns a value with a weak attempt for randomness.
5756(It produces that value based on the current date and time
5757and the address of an internal variable,
5758in case the machine has Address Space Layout Randomization.)
5759
5760}
5761
5740 5762
5741@APIEntry{void luaL_newlib (lua_State *L, const luaL_Reg l[]);| 5763@APIEntry{void luaL_newlib (lua_State *L, const luaL_Reg l[]);|
5742@apii{0,1,m} 5764@apii{0,1,m}
@@ -6909,9 +6931,9 @@ including if necessary a path and an extension.
6909(which may depend on the @N{C compiler} and linker used). 6931(which may depend on the @N{C compiler} and linker used).
6910 6932
6911This functionality is not supported by @N{ISO C}. 6933This functionality is not supported by @N{ISO C}.
6912As such, it is only available on some platforms 6934As such, @id{loadlib} is only available on some platforms:
6913(Windows, Linux, Mac OS X, Solaris, BSD, 6935Linux, Windows, Mac OS X, Solaris, BSD,
6914plus other Unix systems that support the @id{dlfcn} standard). 6936plus other Unix systems that support the @id{dlfcn} standard.
6915 6937
6916This function is inherently insecure, 6938This function is inherently insecure,
6917as it allows Lua to call any function in any readable dynamic 6939as it allows Lua to call any function in any readable dynamic
@@ -8109,7 +8131,7 @@ different sequences of results each time the program runs.
8109 8131
8110When called with at least one argument, 8132When called with at least one argument,
8111the integer parameters @id{x} and @id{y} are 8133the integer parameters @id{x} and @id{y} are
8112joined into a 128-bit @emphx{seed} that 8134joined into a @emphx{seed} that
8113is used to reinitialize the pseudo-random generator; 8135is used to reinitialize the pseudo-random generator;
8114equal seeds produce equal sequences of numbers. 8136equal seeds produce equal sequences of numbers.
8115The default for @id{y} is zero. 8137The default for @id{y} is zero.
@@ -9132,7 +9154,7 @@ is a more portable solution.
9132@simplesect{ 9154@simplesect{
9133 9155
9134Here we list the incompatibilities that you may find when moving a program 9156Here we list the incompatibilities that you may find when moving a program
9135from @N{Lua 5.3} to @N{Lua 5.4}. 9157from @N{Lua 5.4} to @N{Lua 5.5}.
9136 9158
9137You can avoid some incompatibilities by compiling Lua with 9159You can avoid some incompatibilities by compiling Lua with
9138appropriate options (see file @id{luaconf.h}). 9160appropriate options (see file @id{luaconf.h}).
@@ -9169,51 +9191,9 @@ change between versions.
9169@itemize{ 9191@itemize{
9170 9192
9171@item{ 9193@item{
9172The coercion of strings to numbers in 9194The control variable in @Rw{for} loops are read only.
9173arithmetic and bitwise operations 9195If you need to change it,
9174has been removed from the core language. 9196declare a local variable with the same name in the loop body.
9175The string library does a similar job
9176for arithmetic (but not for bitwise) operations
9177using the string metamethods.
9178However, unlike in previous versions,
9179the new implementation preserves the implicit type of the numeral
9180in the string.
9181For instance, the result of @T{"1" + "2"} now is an integer,
9182not a float.
9183}
9184
9185@item{
9186Literal decimal integer constants that overflow are read as floats,
9187instead of wrapping around.
9188You can use hexadecimal notation for such constants if you
9189want the old behavior
9190(reading them as integers with wrap around).
9191}
9192
9193@item{
9194The use of the @idx{__lt} metamethod to emulate @idx{__le}
9195has been removed.
9196When needed, this metamethod must be explicitly defined.
9197}
9198
9199@item{
9200The semantics of the numerical @Rw{for} loop
9201over integers changed in some details.
9202In particular, the control variable never wraps around.
9203}
9204
9205@item{
9206A label for a @Rw{goto} cannot be declared where a label with the same
9207name is visible, even if this other label is declared in an enclosing
9208block.
9209}
9210
9211@item{
9212When finalizing an object,
9213Lua does not ignore @idx{__gc} metamethods that are not functions.
9214Any value will be called, if present.
9215(Non-callable values will generate a warning,
9216like any other error when calling a finalizer.)
9217} 9197}
9218 9198
9219} 9199}
@@ -9224,39 +9204,6 @@ like any other error when calling a finalizer.)
9224@itemize{ 9204@itemize{
9225 9205
9226@item{ 9206@item{
9227The function @Lid{print} does not call @Lid{tostring}
9228to format its arguments;
9229instead, it has this functionality hardwired.
9230You should use @idx{__tostring} to modify how values are printed.
9231}
9232
9233@item{
9234The pseudo-random number generator used by the function @Lid{math.random}
9235now starts with a somewhat random seed.
9236Moreover, it uses a different algorithm.
9237}
9238
9239@item{
9240By default, the decoding functions in the @Lid{utf8} library
9241do not accept surrogates as valid code points.
9242An extra parameter in these functions makes them more permissive.
9243}
9244
9245@item{
9246The options @St{setpause} and @St{setstepmul}
9247of the function @Lid{collectgarbage} are deprecated.
9248You should use the new option @St{incremental} to set them.
9249}
9250
9251@item{
9252The function @Lid{io.lines} now returns four values,
9253instead of just one.
9254That can be a problem when it is used as the sole
9255argument to another function that has optional parameters,
9256such as in @T{load(io.lines(filename, "L"))}.
9257To fix that issue,
9258you can wrap the call into parentheses,
9259to adjust its number of results to one.
9260} 9207}
9261 9208
9262} 9209}
@@ -9268,46 +9215,6 @@ to adjust its number of results to one.
9268@itemize{ 9215@itemize{
9269 9216
9270@item{ 9217@item{
9271Full userdata now has an arbitrary number of associated user values.
9272Therefore, the functions @id{lua_newuserdata},
9273@id{lua_setuservalue}, and @id{lua_getuservalue} were
9274replaced by @Lid{lua_newuserdatauv},
9275@Lid{lua_setiuservalue}, and @Lid{lua_getiuservalue},
9276which have an extra argument.
9277
9278For compatibility, the old names still work as macros assuming
9279one single user value.
9280Note, however, that userdata with zero user values
9281are more efficient memory-wise.
9282}
9283
9284@item{
9285The function @Lid{lua_resume} has an extra parameter.
9286This out parameter returns the number of values on
9287the top of the stack that were yielded or returned by the coroutine.
9288(In previous versions,
9289those values were the entire stack.)
9290}
9291
9292@item{
9293The function @Lid{lua_version} returns the version number,
9294instead of an address of the version number.
9295The Lua core should work correctly with libraries using their
9296own static copies of the same core,
9297so there is no need to check whether they are using the same
9298address space.
9299}
9300
9301@item{
9302The constant @id{LUA_ERRGCMM} was removed.
9303Errors in finalizers are never propagated;
9304instead, they generate a warning.
9305}
9306
9307@item{
9308The options @idx{LUA_GCSETPAUSE} and @idx{LUA_GCSETSTEPMUL}
9309of the function @Lid{lua_gc} are deprecated.
9310You should use the new option @id{LUA_GCINC} to set them.
9311} 9218}
9312 9219
9313} 9220}
diff --git a/testes/all.lua b/testes/all.lua
index 5df0ff9b..3c1ff5c7 100644
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -3,7 +3,7 @@
3-- See Copyright Notice at the end of this file 3-- See Copyright Notice at the end of this file
4 4
5 5
6local version = "Lua 5.4" 6local version = "Lua 5.5"
7if _VERSION ~= version then 7if _VERSION ~= version then
8 io.stderr:write("This test suite is for ", version, 8 io.stderr:write("This test suite is for ", version,
9 ", not for ", _VERSION, "\nExiting tests") 9 ", not for ", _VERSION, "\nExiting tests")
diff --git a/testes/api.lua b/testes/api.lua
index 752ff18f..181c1d53 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -407,7 +407,7 @@ do
407 concat 3]]) == "hi alo mundo") 407 concat 3]]) == "hi alo mundo")
408 408
409 -- "argerror" without frames 409 -- "argerror" without frames
410 assert(T.checkpanic("loadstring 4") == 410 assert(T.checkpanic("loadstring 4 name bt") ==
411 "bad argument #4 (string expected, got no value)") 411 "bad argument #4 (string expected, got no value)")
412 412
413 413
@@ -420,7 +420,7 @@ do
420 if not _soft then 420 if not _soft then
421 local msg = T.checkpanic[[ 421 local msg = T.checkpanic[[
422 pushstring "function f() f() end" 422 pushstring "function f() f() end"
423 loadstring -1; call 0 0 423 loadstring -1 name t; call 0 0
424 getglobal f; call 0 0 424 getglobal f; call 0 0
425 ]] 425 ]]
426 assert(string.find(msg, "stack overflow")) 426 assert(string.find(msg, "stack overflow"))
@@ -430,7 +430,7 @@ do
430 assert(T.checkpanic([[ 430 assert(T.checkpanic([[
431 pushstring "return {__close = function () Y = 'ho'; end}" 431 pushstring "return {__close = function () Y = 'ho'; end}"
432 newtable 432 newtable
433 loadstring -2 433 loadstring -2 name t
434 call 0 1 434 call 0 1
435 setmetatable -2 435 setmetatable -2
436 toclose -1 436 toclose -1
@@ -458,6 +458,8 @@ if not _soft then
458 print'+' 458 print'+'
459end 459end
460 460
461
462
461local lim = _soft and 500 or 12000 463local lim = _soft and 500 or 12000
462local prog = {"checkstack " .. (lim * 2 + 100) .. "msg", "newtable"} 464local prog = {"checkstack " .. (lim * 2 + 100) .. "msg", "newtable"}
463for i = 1,lim do 465for i = 1,lim do
@@ -481,10 +483,20 @@ for i = 1,lim do assert(t[i] == i*10); t[i] = undef end
481assert(next(t) == nil) 483assert(next(t) == nil)
482prog, g, t = nil 484prog, g, t = nil
483 485
486do -- shrink stack
487 local m1, m2 = 0, collectgarbage"count" * 1024
488 while m1 ~= m2 do -- repeat until stable
489 collectgarbage()
490 m1 = m2
491 m2 = collectgarbage"count" * 1024
492 end
493end
494
495
484-- testing errors 496-- testing errors
485 497
486a = T.testC([[ 498a = T.testC([[
487 loadstring 2; pcall 0 1 0; 499 loadstring 2 name t; pcall 0 1 0;
488 pushvalue 3; insert -2; pcall 1 1 0; 500 pushvalue 3; insert -2; pcall 1 1 0;
489 pcall 0 0 0; 501 pcall 0 0 0;
490 return 1 502 return 1
@@ -498,7 +510,7 @@ local function check3(p, ...)
498 assert(#arg == 3) 510 assert(#arg == 3)
499 assert(string.find(arg[3], p)) 511 assert(string.find(arg[3], p))
500end 512end
501check3(":1:", T.testC("loadstring 2; return *", "x=")) 513check3(":1:", T.testC("loadstring 2 name t; return *", "x="))
502check3("%.", T.testC("loadfile 2; return *", ".")) 514check3("%.", T.testC("loadfile 2; return *", "."))
503check3("xxxx", T.testC("loadfile 2; return *", "xxxx")) 515check3("xxxx", T.testC("loadfile 2; return *", "xxxx"))
504 516
@@ -509,6 +521,35 @@ local function checkerrnopro (code, msg)
509 assert(not stt and string.find(err, msg)) 521 assert(not stt and string.find(err, msg))
510end 522end
511 523
524
525do
526 print("testing load of binaries in fixed buffers")
527 local source = {}
528 local N = 1000
529 -- create a somewhat "large" source
530 for i = 1, N do source[i] = "X = X + 1; " end
531 source = table.concat(source)
532 -- give chunk an explicit name to avoid using source as name
533 source = load(source, "name1")
534 -- dump without debug information
535 source = string.dump(source, true)
536 -- each "X=X+1" generates 4 opcodes with 4 bytes each
537 assert(#source > N * 4 * 4)
538 collectgarbage(); collectgarbage()
539 local m1 = collectgarbage"count" * 1024
540 -- load dump using fixed buffer
541 local code = T.testC([[
542 loadstring 2 name B;
543 return 1
544 ]], source)
545 collectgarbage()
546 local m2 = collectgarbage"count" * 1024
547 -- load used fewer than 300 bytes
548 assert(m2 > m1 and m2 - m1 < 300)
549 X = 0; code(); assert(X == N); X = nil
550end
551
552
512if not _soft then 553if not _soft then
513 collectgarbage("stop") -- avoid __gc with full stack 554 collectgarbage("stop") -- avoid __gc with full stack
514 checkerrnopro("pushnum 3; call 0 0", "attempt to call") 555 checkerrnopro("pushnum 3; call 0 0", "attempt to call")
@@ -1046,10 +1087,12 @@ assert(a == nil and c == 2) -- 2 == run-time error
1046a, b, c = T.doremote(L1, "return a+") 1087a, b, c = T.doremote(L1, "return a+")
1047assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error 1088assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
1048 1089
1049T.loadlib(L1) 1090T.loadlib(L1, 2) -- load only 'package'
1050a, b, c = T.doremote(L1, [[ 1091a, b, c = T.doremote(L1, [[
1051 string = require'string' 1092 string = require'string'
1052 a = require'_G'; assert(a == _G and require("_G") == a) 1093 local initialG = _G -- not loaded yet
1094 local a = require'_G'; assert(a == _G and require("_G") == a)
1095 assert(initialG == nil and io == nil) -- now we have 'assert'
1053 io = require'io'; assert(type(io.read) == "function") 1096 io = require'io'; assert(type(io.read) == "function")
1054 assert(require("io") == io) 1097 assert(require("io") == io)
1055 a = require'table'; assert(type(a.insert) == "function") 1098 a = require'table'; assert(type(a.insert) == "function")
@@ -1063,7 +1106,7 @@ T.closestate(L1);
1063 1106
1064 1107
1065L1 = T.newstate() 1108L1 = T.newstate()
1066T.loadlib(L1) 1109T.loadlib(L1, 0)
1067T.doremote(L1, "a = {}") 1110T.doremote(L1, "a = {}")
1068T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1; 1111T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
1069 settable -3]]) 1112 settable -3]])
@@ -1446,10 +1489,10 @@ end
1446 1489
1447do -- garbage collection with no extra memory 1490do -- garbage collection with no extra memory
1448 local L = T.newstate() 1491 local L = T.newstate()
1449 T.loadlib(L) 1492 T.loadlib(L, 1 | 2) -- load _G and 'package'
1450 local res = (T.doremote(L, [[ 1493 local res = (T.doremote(L, [[
1451 _ENV = require"_G" 1494 _ENV = _G
1452 local T = require"T" 1495 assert(string == nil)
1453 local a = {} 1496 local a = {}
1454 for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table 1497 for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table
1455 local stsize, stuse = T.querystr() 1498 local stsize, stuse = T.querystr()
diff --git a/testes/attrib.lua b/testes/attrib.lua
index 458488a8..9054e0b6 100644
--- a/testes/attrib.lua
+++ b/testes/attrib.lua
@@ -236,7 +236,7 @@ package.path = oldpath
236local fname = "file_does_not_exist2" 236local fname = "file_does_not_exist2"
237local m, err = pcall(require, fname) 237local m, err = pcall(require, fname)
238for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do 238for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do
239 t = string.gsub(t, "?", fname) 239 local t = string.gsub(t, "?", fname)
240 assert(string.find(err, t, 1, true)) 240 assert(string.find(err, t, 1, true))
241end 241end
242 242
diff --git a/testes/calls.lua b/testes/calls.lua
index a1938584..9a5eed0b 100644
--- a/testes/calls.lua
+++ b/testes/calls.lua
@@ -454,7 +454,7 @@ print("testing binary chunks")
454do 454do
455 local header = string.pack("c4BBc6BBB", 455 local header = string.pack("c4BBc6BBB",
456 "\27Lua", -- signature 456 "\27Lua", -- signature
457 0x54, -- version 5.4 (0x54) 457 0x55, -- version 5.5 (0x55)
458 0, -- format 458 0, -- format
459 "\x19\x93\r\n\x1a\n", -- data 459 "\x19\x93\r\n\x1a\n", -- data
460 4, -- size of instruction 460 4, -- size of instruction
@@ -493,5 +493,30 @@ do
493 end 493 end
494end 494end
495 495
496
497do -- check reuse of strings in dumps
498 local str = "|" .. string.rep("X", 50) .. "|"
499 local foo = load(string.format([[
500 local str <const> = "%s"
501 return {
502 function () return str end,
503 function () return str end,
504 function () return str end
505 }
506 ]], str))
507 -- count occurrences of 'str' inside the dump
508 local dump = string.dump(foo)
509 local _, count = string.gsub(dump, str, {})
510 -- there should be only two occurrences:
511 -- one inside the source, other the string itself.
512 assert(count == 2)
513
514 if T then -- check reuse of strings in undump
515 local funcs = load(dump)()
516 assert(string.format("%p", T.listk(funcs[1])[1]) ==
517 string.format("%p", T.listk(funcs[3])[1]))
518 end
519end
520
496print('OK') 521print('OK')
497return deep 522return deep
diff --git a/testes/closure.lua b/testes/closure.lua
index ea038e82..de1b54ec 100644
--- a/testes/closure.lua
+++ b/testes/closure.lua
@@ -60,32 +60,29 @@ end
60-- testing closures with 'for' control variable 60-- testing closures with 'for' control variable
61a = {} 61a = {}
62for i=1,10 do 62for i=1,10 do
63 a[i] = {set = function(x) i=x end, get = function () return i end} 63 a[i] = function () return i end
64 if i == 3 then break end 64 if i == 3 then break end
65end 65end
66assert(a[4] == undef) 66assert(a[4] == undef)
67a[1].set(10) 67assert(a[2]() == 2)
68assert(a[2].get() == 2) 68assert(a[3]() == 3)
69a[2].set('a')
70assert(a[3].get() == 3)
71assert(a[2].get() == 'a')
72 69
73a = {} 70a = {}
74local t = {"a", "b"} 71local t = {"a", "b"}
75for i = 1, #t do 72for i = 1, #t do
76 local k = t[i] 73 local k = t[i]
77 a[i] = {set = function(x, y) i=x; k=y end, 74 a[i] = {set = function(x) k=x end,
78 get = function () return i, k end} 75 get = function () return i, k end}
79 if i == 2 then break end 76 if i == 2 then break end
80end 77end
81a[1].set(10, 20) 78a[1].set(10)
82local r,s = a[2].get() 79local r,s = a[2].get()
83assert(r == 2 and s == 'b') 80assert(r == 2 and s == 'b')
84r,s = a[1].get() 81r,s = a[1].get()
85assert(r == 10 and s == 20) 82assert(r == 1 and s == 10)
86a[2].set('a', 'b') 83a[2].set('a')
87r,s = a[2].get() 84r,s = a[2].get()
88assert(r == "a" and s == "b") 85assert(r == 2 and s == "a")
89 86
90 87
91-- testing closures with 'for' control variable x break 88-- testing closures with 'for' control variable x break
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index de7e46fb..990da8c4 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -703,7 +703,7 @@ else
703 703
704 T.testC(state, "settop 0") 704 T.testC(state, "settop 0")
705 705
706 T.loadlib(state) 706 T.loadlib(state, 1 | 2) -- load _G and 'package'
707 707
708 assert(T.doremote(state, [[ 708 assert(T.doremote(state, [[
709 coroutine = require'coroutine'; 709 coroutine = require'coroutine';
diff --git a/testes/files.lua b/testes/files.lua
index 1476006e..2582406f 100644
--- a/testes/files.lua
+++ b/testes/files.lua
@@ -427,12 +427,12 @@ do -- testing closing file in line iteration
427 -- get the to-be-closed variable from a loop 427 -- get the to-be-closed variable from a loop
428 local function gettoclose (lv) 428 local function gettoclose (lv)
429 lv = lv + 1 429 lv = lv + 1
430 local stvar = 0 -- to-be-closed is 4th state variable in the loop 430 local stvar = 0 -- to-be-closed is 3th state variable in the loop
431 for i = 1, 1000 do 431 for i = 1, 1000 do
432 local n, v = debug.getlocal(lv, i) 432 local n, v = debug.getlocal(lv, i)
433 if n == "(for state)" then 433 if n == "(for state)" then
434 stvar = stvar + 1 434 stvar = stvar + 1
435 if stvar == 4 then return v end 435 if stvar == 3 then return v end
436 end 436 end
437 end 437 end
438 end 438 end
diff --git a/testes/main.lua b/testes/main.lua
index 11b14b44..dde72a74 100644
--- a/testes/main.lua
+++ b/testes/main.lua
@@ -137,7 +137,7 @@ RUN('env LUA_INIT= LUA_PATH=x lua %s > %s', prog, out)
137checkout("x\n") 137checkout("x\n")
138 138
139-- test LUA_PATH_version 139-- test LUA_PATH_version
140RUN('env LUA_INIT= LUA_PATH_5_4=y LUA_PATH=x lua %s > %s', prog, out) 140RUN('env LUA_INIT= LUA_PATH_5_5=y LUA_PATH=x lua %s > %s', prog, out)
141checkout("y\n") 141checkout("y\n")
142 142
143-- test LUA_CPATH 143-- test LUA_CPATH
@@ -146,7 +146,7 @@ RUN('env LUA_INIT= LUA_CPATH=xuxu lua %s > %s', prog, out)
146checkout("xuxu\n") 146checkout("xuxu\n")
147 147
148-- test LUA_CPATH_version 148-- test LUA_CPATH_version
149RUN('env LUA_INIT= LUA_CPATH_5_4=yacc LUA_CPATH=x lua %s > %s', prog, out) 149RUN('env LUA_INIT= LUA_CPATH_5_5=yacc LUA_CPATH=x lua %s > %s', prog, out)
150checkout("yacc\n") 150checkout("yacc\n")
151 151
152-- test LUA_INIT (and its access to 'arg' table) 152-- test LUA_INIT (and its access to 'arg' table)
@@ -156,7 +156,7 @@ checkout("3.2\n")
156 156
157-- test LUA_INIT_version 157-- test LUA_INIT_version
158prepfile("print(X)") 158prepfile("print(X)")
159RUN('env LUA_INIT_5_4="X=10" LUA_INIT="X=3" lua %s > %s', prog, out) 159RUN('env LUA_INIT_5_5="X=10" LUA_INIT="X=3" lua %s > %s', prog, out)
160checkout("10\n") 160checkout("10\n")
161 161
162-- test LUA_INIT for files 162-- test LUA_INIT for files
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index 02b7dea2..5d8796f7 100644
--- a/testes/nextvar.lua
+++ b/testes/nextvar.lua
@@ -210,9 +210,9 @@ assert(T.querytab(a) == 64) -- array part has 64 elements
210a[32] = true; a[48] = true; -- binary search will find these ones 210a[32] = true; a[48] = true; -- binary search will find these ones
211a[51] = true -- binary search will miss this one 211a[51] = true -- binary search will miss this one
212assert(#a == 48) -- this will set the limit 212assert(#a == 48) -- this will set the limit
213assert(select(4, T.querytab(a)) == 48) -- this is the limit now 213assert(select(3, T.querytab(a)) == 48) -- this is the limit now
214a[50] = true -- this will set a new limit 214a[50] = true -- this will set a new limit
215assert(select(4, T.querytab(a)) == 50) -- this is the limit now 215assert(select(3, T.querytab(a)) == 50) -- this is the limit now
216-- but the size is larger (and still inside the array part) 216-- but the size is larger (and still inside the array part)
217assert(#a == 51) 217assert(#a == 51)
218 218
@@ -609,10 +609,12 @@ do
609 a = 0; for i=1.0, 0.99999, -1 do a=a+1 end; assert(a==1) 609 a = 0; for i=1.0, 0.99999, -1 do a=a+1 end; assert(a==1)
610end 610end
611 611
612do -- changing the control variable 612do -- attempt to change the control variable
613 local a 613 local st, msg = load "for i = 1, 10 do i = 10 end"
614 a = 0; for i = 1, 10 do a = a + 1; i = "x" end; assert(a == 10) 614 assert(not st and string.find(msg, "assign to const variable 'i'"))
615 a = 0; for i = 10.0, 1, -1 do a = a + 1; i = "x" end; assert(a == 10) 615
616 local st, msg = load "for v, k in pairs{} do v = 10 end"
617 assert(not st and string.find(msg, "assign to const variable 'v'"))
616end 618end
617 619
618-- conversion 620-- conversion