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 332e97d1..767fa55e 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1107,16 +1107,37 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
1107} 1107}
1108 1108
1109 1109
1110/*
1111** Dump a function, calling 'writer' to write its parts. Because the
1112** writer can use the stack in unkown ways, this function should not
1113** push things on the stack, but it must anchor an auxiliary table
1114** used by 'luaU_dump'. To do so, it creates the table, anchors the
1115** function that is on the stack in the table, and substitutes the
1116** table for the function in the stack.
1117*/
1118
1110LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { 1119LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
1111 int status; 1120 int status;
1121 StkId fstk; /* pointer to function */
1112 TValue *o; 1122 TValue *o;
1113 lua_lock(L); 1123 lua_lock(L);
1114 api_checknelems(L, 1); 1124 api_checknelems(L, 1);
1115 o = s2v(L->top.p - 1); 1125 fstk = L->top.p - 1;
1116 if (isLfunction(o)) 1126 o = s2v(fstk);
1117 status = luaU_dump(L, getproto(o), writer, data, strip); 1127 if (!isLfunction(o))
1118 else
1119 status = 1; 1128 status = 1;
1129 else {
1130 LClosure *f = clLvalue(o);
1131 ptrdiff_t fidx = savestack(L, fstk); /* function index */
1132 Table *h = luaH_new(L); /* auxiliary table used by 'luaU_dump' */
1133 sethvalue2s(L, L->top.p, h); /* anchor it (luaH_set may call GC) */
1134 L->top.p++; /* (assume extra slot) */
1135 luaH_set(L, h, o, o); /* anchor function into table */
1136 setobjs2s(L, fstk, L->top.p - 1); /* move table over function */
1137 L->top.p--; /* stack back to initial size */
1138 status = luaU_dump(L, f->p, writer, data, strip, h);
1139 setclLvalue2s(L, restorestack(L, fidx), f); /* put function back */
1140 }
1120 lua_unlock(L); 1141 lua_unlock(L);
1121 return status; 1142 return status;
1122} 1143}
@@ -1145,7 +1166,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1145 } 1166 }
1146 case LUA_GCRESTART: { 1167 case LUA_GCRESTART: {
1147 luaE_setdebt(g, 0); 1168 luaE_setdebt(g, 0);
1148 g->gcstp = 0; /* (GCSTPGC must be already zero here) */ 1169 g->gcstp = 0; /* (bit GCSTPGC must be zero here) */
1149 break; 1170 break;
1150 } 1171 }
1151 case LUA_GCCOLLECT: { 1172 case LUA_GCCOLLECT: {
@@ -1154,42 +1175,46 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1154 } 1175 }
1155 case LUA_GCCOUNT: { 1176 case LUA_GCCOUNT: {
1156 /* GC values are expressed in Kbytes: #bytes/2^10 */ 1177 /* GC values are expressed in Kbytes: #bytes/2^10 */
1157 res = cast_int(gettotalbytes(g) >> 10); 1178 res = cast_int(g->totalbytes >> 10);
1158 break; 1179 break;
1159 } 1180 }
1160 case LUA_GCCOUNTB: { 1181 case LUA_GCCOUNTB: {
1161 res = cast_int(gettotalbytes(g) & 0x3ff); 1182 res = cast_int(g->totalbytes & 0x3ff);
1162 break; 1183 break;
1163 } 1184 }
1164 case LUA_GCSTEP: { 1185 case LUA_GCSTEP: {
1165 int data = va_arg(argp, int); 1186 int todo = va_arg(argp, int); /* work to be done */
1166 l_mem debt = 1; /* =1 to signal that it did an actual step */ 1187 int didsomething = 0;
1167 lu_byte oldstp = g->gcstp; 1188 lu_byte oldstp = g->gcstp;
1168 g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */ 1189 g->gcstp = 0; /* allow GC to run (bit GCSTPGC must be zero here) */
1169 if (data == 0) { 1190 if (todo == 0)
1170 luaE_setdebt(g, 0); /* do a basic step */ 1191 todo = 1 << g->gcstepsize; /* standard step size */
1171 luaC_step(L); 1192 while (todo >= g->GCdebt) { /* enough to run a step? */
1172 } 1193 todo -= g->GCdebt; /* decrement 'todo' */
1173 else { /* add 'data' to total debt */ 1194 luaC_step(L); /* run one basic step */
1174 debt = cast(l_mem, data) * 1024 + g->GCdebt; 1195 didsomething = 1;
1175 luaE_setdebt(g, debt); 1196 if (g->gckind == KGC_GEN) /* minor collections? */
1176 luaC_checkGC(L); 1197 todo = 0; /* doesn't make sense to repeat in this case */
1198 else if (g->gcstate == GCSpause)
1199 break; /* don't run more than one cycle */
1177 } 1200 }
1201 /* remove remaining 'todo' from total debt */
1202 luaE_setdebt(g, g->GCdebt - todo);
1178 g->gcstp = oldstp; /* restore previous state */ 1203 g->gcstp = oldstp; /* restore previous state */
1179 if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ 1204 if (didsomething && g->gcstate == GCSpause) /* end of cycle? */
1180 res = 1; /* signal it */ 1205 res = 1; /* signal it */
1181 break; 1206 break;
1182 } 1207 }
1183 case LUA_GCSETPAUSE: { 1208 case LUA_GCSETPAUSE: {
1184 int data = va_arg(argp, int); 1209 unsigned int data = va_arg(argp, unsigned int);
1185 res = getgcparam(g->gcpause); 1210 res = applygcparam(g, gcpause, 100);
1186 setgcparam(g->gcpause, data); 1211 setgcparam(g, gcpause, data);
1187 break; 1212 break;
1188 } 1213 }
1189 case LUA_GCSETSTEPMUL: { 1214 case LUA_GCSETSTEPMUL: {
1190 int data = va_arg(argp, int); 1215 unsigned int data = va_arg(argp, unsigned int);
1191 res = getgcparam(g->gcstepmul); 1216 res = applygcparam(g, gcstepmul, 100);
1192 setgcparam(g->gcstepmul, data); 1217 setgcparam(g, gcstepmul, data);
1193 break; 1218 break;
1194 } 1219 }
1195 case LUA_GCISRUNNING: { 1220 case LUA_GCISRUNNING: {
@@ -1197,27 +1222,28 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1197 break; 1222 break;
1198 } 1223 }
1199 case LUA_GCGEN: { 1224 case LUA_GCGEN: {
1200 int minormul = va_arg(argp, int); 1225 unsigned int minormul = va_arg(argp, unsigned int);
1201 int majormul = va_arg(argp, int); 1226 unsigned int majormul = va_arg(argp, unsigned int);
1202 res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1227 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1203 if (minormul != 0) 1228 if (minormul != 0)
1204 g->genminormul = minormul; 1229 setgcparam(g, genminormul, minormul);
1205 if (majormul != 0) 1230 if (majormul != 0)
1206 setgcparam(g->genmajormul, majormul); 1231 setgcparam(g, genmajormul, majormul);
1207 luaC_changemode(L, KGC_GEN); 1232 luaC_changemode(L, KGC_GEN);
1208 break; 1233 break;
1209 } 1234 }
1210 case LUA_GCINC: { 1235 case LUA_GCINC: {
1211 int pause = va_arg(argp, int); 1236 unsigned int pause = va_arg(argp, unsigned int);
1212 int stepmul = va_arg(argp, int); 1237 unsigned int stepmul = va_arg(argp, unsigned int);
1213 int stepsize = va_arg(argp, int); 1238 unsigned int stepsize = va_arg(argp, unsigned int);
1214 res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1239 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1215 if (pause != 0) 1240 if (pause != 0)
1216 setgcparam(g->gcpause, pause); 1241 setgcparam(g, gcpause, pause);
1217 if (stepmul != 0) 1242 if (stepmul != 0)
1218 setgcparam(g->gcstepmul, stepmul); 1243 setgcparam(g, gcstepmul, stepmul);
1219 if (stepsize != 0) 1244 if (stepsize != 0)
1220 g->gcstepsize = stepsize; 1245 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
1246 : log2maxs(l_obj);
1221 luaC_changemode(L, KGC_INC); 1247 luaC_changemode(L, KGC_INC);
1222 break; 1248 break;
1223 } 1249 }
@@ -1285,13 +1311,14 @@ LUA_API void lua_toclose (lua_State *L, int idx) {
1285LUA_API void lua_concat (lua_State *L, int n) { 1311LUA_API void lua_concat (lua_State *L, int n) {
1286 lua_lock(L); 1312 lua_lock(L);
1287 api_checknelems(L, n); 1313 api_checknelems(L, n);
1288 if (n > 0) 1314 if (n > 0) {
1289 luaV_concat(L, n); 1315 luaV_concat(L, n);
1316 luaC_checkGC(L);
1317 }
1290 else { /* nothing to concatenate */ 1318 else { /* nothing to concatenate */
1291 setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ 1319 setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */
1292 api_incr_top(L); 1320 api_incr_top(L);
1293 } 1321 }
1294 luaC_checkGC(L);
1295 lua_unlock(L); 1322 lua_unlock(L);
1296} 1323}
1297 1324
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 caac6ba3..914d8cd0 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 253a2892..81682454 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 */
@@ -105,7 +87,7 @@
105#define markobjectN(g,t) { if (t) markobject(g,t); } 87#define markobjectN(g,t) { if (t) markobject(g,t); }
106 88
107static void reallymarkobject (global_State *g, GCObject *o); 89static void reallymarkobject (global_State *g, GCObject *o);
108static lu_mem atomic (lua_State *L); 90static l_obj atomic (lua_State *L);
109static void entersweep (lua_State *L); 91static void entersweep (lua_State *L);
110 92
111 93
@@ -217,7 +199,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
217 } 199 }
218 else { /* sweep phase */ 200 else { /* sweep phase */
219 lua_assert(issweepphase(g)); 201 lua_assert(issweepphase(g));
220 if (g->gckind == KGC_INC) /* incremental mode? */ 202 if (g->gckind != KGC_GEN) /* incremental mode? */
221 makewhite(g, o); /* mark 'o' as white to avoid other barriers */ 203 makewhite(g, o); /* mark 'o' as white to avoid other barriers */
222 } 204 }
223} 205}
@@ -259,6 +241,7 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
259 global_State *g = G(L); 241 global_State *g = G(L);
260 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); 242 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz));
261 GCObject *o = cast(GCObject *, p + offset); 243 GCObject *o = cast(GCObject *, p + offset);
244 g->GCdebt--;
262 o->marked = luaC_white(g); 245 o->marked = luaC_white(g);
263 o->tt = tt; 246 o->tt = tt;
264 o->next = g->allgc; 247 o->next = g->allgc;
@@ -267,6 +250,9 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
267} 250}
268 251
269 252
253/*
254** create a new collectable object with no offset.
255*/
270GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { 256GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
271 return luaC_newobjdt(L, tt, sz, 0); 257 return luaC_newobjdt(L, tt, sz, 0);
272} 258}
@@ -295,6 +281,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
295** (only closures can), and a userdata's metatable must be a table. 281** (only closures can), and a userdata's metatable must be a table.
296*/ 282*/
297static void reallymarkobject (global_State *g, GCObject *o) { 283static void reallymarkobject (global_State *g, GCObject *o) {
284 g->marked++;
298 switch (o->tt) { 285 switch (o->tt) {
299 case LUA_VSHRSTR: 286 case LUA_VSHRSTR:
300 case LUA_VLNGSTR: { 287 case LUA_VLNGSTR: {
@@ -342,9 +329,9 @@ static void markmt (global_State *g) {
342/* 329/*
343** mark all objects in list of being-finalized 330** mark all objects in list of being-finalized
344*/ 331*/
345static lu_mem markbeingfnz (global_State *g) { 332static l_obj markbeingfnz (global_State *g) {
346 GCObject *o; 333 GCObject *o;
347 lu_mem count = 0; 334 l_obj count = 0;
348 for (o = g->tobefnz; o != NULL; o = o->next) { 335 for (o = g->tobefnz; o != NULL; o = o->next) {
349 count++; 336 count++;
350 markobject(g, o); 337 markobject(g, o);
@@ -364,12 +351,11 @@ static lu_mem markbeingfnz (global_State *g) {
364** upvalues, as they have nothing to be checked. (If the thread gets an 351** upvalues, as they have nothing to be checked. (If the thread gets an
365** upvalue later, it will be linked in the list again.) 352** upvalue later, it will be linked in the list again.)
366*/ 353*/
367static int remarkupvals (global_State *g) { 354static l_obj remarkupvals (global_State *g) {
355 l_obj work = 0;
368 lua_State *thread; 356 lua_State *thread;
369 lua_State **p = &g->twups; 357 lua_State **p = &g->twups;
370 int work = 0; /* estimate of how much work was done here */
371 while ((thread = *p) != NULL) { 358 while ((thread = *p) != NULL) {
372 work++;
373 if (!iswhite(thread) && thread->openupval != NULL) 359 if (!iswhite(thread) && thread->openupval != NULL)
374 p = &thread->twups; /* keep marked thread with upvalues in the list */ 360 p = &thread->twups; /* keep marked thread with upvalues in the list */
375 else { /* thread is not marked or without upvalues */ 361 else { /* thread is not marked or without upvalues */
@@ -379,13 +365,13 @@ static int remarkupvals (global_State *g) {
379 thread->twups = thread; /* mark that it is out of list */ 365 thread->twups = thread; /* mark that it is out of list */
380 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { 366 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
381 lua_assert(getage(uv) <= getage(thread)); 367 lua_assert(getage(uv) <= getage(thread));
382 work++;
383 if (!iswhite(uv)) { /* upvalue already visited? */ 368 if (!iswhite(uv)) { /* upvalue already visited? */
384 lua_assert(upisopen(uv) && isgray(uv)); 369 lua_assert(upisopen(uv) && isgray(uv));
385 markvalue(g, uv->v.p); /* mark its value */ 370 markvalue(g, uv->v.p); /* mark its value */
386 } 371 }
387 } 372 }
388 } 373 }
374 work++;
389 } 375 }
390 return work; 376 return work;
391} 377}
@@ -398,10 +384,15 @@ static void cleargraylists (global_State *g) {
398 384
399 385
400/* 386/*
401** mark root set and reset all gray lists, to start a new collection 387** mark root set and reset all gray lists, to start a new collection.
388** 'marked' is initialized with the number of fixed objects in the state,
389** to count the total number of live objects during a cycle. (That is
390** the metafield names, plus the reserved words, plus "_ENV" plus the
391** memory-error message.)
402*/ 392*/
403static void restartcollection (global_State *g) { 393static void restartcollection (global_State *g) {
404 cleargraylists(g); 394 cleargraylists(g);
395 g->marked = NFIXED;
405 markobject(g, g->mainthread); 396 markobject(g, g->mainthread);
406 markvalue(g, &g->l_registry); 397 markvalue(g, &g->l_registry);
407 markmt(g); 398 markmt(g);
@@ -539,7 +530,7 @@ static void traversestrongtable (global_State *g, Table *h) {
539} 530}
540 531
541 532
542static lu_mem traversetable (global_State *g, Table *h) { 533static void traversetable (global_State *g, Table *h) {
543 const char *weakkey, *weakvalue; 534 const char *weakkey, *weakvalue;
544 const TValue *mode = gfasttm(g, h->metatable, TM_MODE); 535 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
545 TString *smode; 536 TString *smode;
@@ -558,17 +549,15 @@ static lu_mem traversetable (global_State *g, Table *h) {
558 } 549 }
559 else /* not weak */ 550 else /* not weak */
560 traversestrongtable(g, h); 551 traversestrongtable(g, h);
561 return 1 + h->alimit + 2 * allocsizenode(h);
562} 552}
563 553
564 554
565static int traverseudata (global_State *g, Udata *u) { 555static void traverseudata (global_State *g, Udata *u) {
566 int i; 556 int i;
567 markobjectN(g, u->metatable); /* mark its metatable */ 557 markobjectN(g, u->metatable); /* mark its metatable */
568 for (i = 0; i < u->nuvalue; i++) 558 for (i = 0; i < u->nuvalue; i++)
569 markvalue(g, &u->uv[i].uv); 559 markvalue(g, &u->uv[i].uv);
570 genlink(g, obj2gco(u)); 560 genlink(g, obj2gco(u));
571 return 1 + u->nuvalue;
572} 561}
573 562
574 563
@@ -577,7 +566,7 @@ static int traverseudata (global_State *g, Udata *u) {
577** arrays can be larger than needed; the extra slots are filled with 566** arrays can be larger than needed; the extra slots are filled with
578** NULL, so the use of 'markobjectN') 567** NULL, so the use of 'markobjectN')
579*/ 568*/
580static int traverseproto (global_State *g, Proto *f) { 569static void traverseproto (global_State *g, Proto *f) {
581 int i; 570 int i;
582 markobjectN(g, f->source); 571 markobjectN(g, f->source);
583 for (i = 0; i < f->sizek; i++) /* mark literals */ 572 for (i = 0; i < f->sizek; i++) /* mark literals */
@@ -588,29 +577,26 @@ static int traverseproto (global_State *g, Proto *f) {
588 markobjectN(g, f->p[i]); 577 markobjectN(g, f->p[i]);
589 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ 578 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
590 markobjectN(g, f->locvars[i].varname); 579 markobjectN(g, f->locvars[i].varname);
591 return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
592} 580}
593 581
594 582
595static int traverseCclosure (global_State *g, CClosure *cl) { 583static void traverseCclosure (global_State *g, CClosure *cl) {
596 int i; 584 int i;
597 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ 585 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
598 markvalue(g, &cl->upvalue[i]); 586 markvalue(g, &cl->upvalue[i]);
599 return 1 + cl->nupvalues;
600} 587}
601 588
602/* 589/*
603** Traverse a Lua closure, marking its prototype and its upvalues. 590** Traverse a Lua closure, marking its prototype and its upvalues.
604** (Both can be NULL while closure is being created.) 591** (Both can be NULL while closure is being created.)
605*/ 592*/
606static int traverseLclosure (global_State *g, LClosure *cl) { 593static void traverseLclosure (global_State *g, LClosure *cl) {
607 int i; 594 int i;
608 markobjectN(g, cl->p); /* mark its prototype */ 595 markobjectN(g, cl->p); /* mark its prototype */
609 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ 596 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */
610 UpVal *uv = cl->upvals[i]; 597 UpVal *uv = cl->upvals[i];
611 markobjectN(g, uv); /* mark upvalue */ 598 markobjectN(g, uv); /* mark upvalue */
612 } 599 }
613 return 1 + cl->nupvalues;
614} 600}
615 601
616 602
@@ -626,13 +612,13 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
626** (which can only happen in generational mode) or if the traverse is in 612** (which can only happen in generational mode) or if the traverse is in
627** the propagate phase (which can only happen in incremental mode). 613** the propagate phase (which can only happen in incremental mode).
628*/ 614*/
629static int traversethread (global_State *g, lua_State *th) { 615static void traversethread (global_State *g, lua_State *th) {
630 UpVal *uv; 616 UpVal *uv;
631 StkId o = th->stack.p; 617 StkId o = th->stack.p;
632 if (isold(th) || g->gcstate == GCSpropagate) 618 if (isold(th) || g->gcstate == GCSpropagate)
633 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 619 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
634 if (o == NULL) 620 if (o == NULL)
635 return 1; /* stack not completely built yet */ 621 return; /* stack not completely built yet */
636 lua_assert(g->gcstate == GCSatomic || 622 lua_assert(g->gcstate == GCSatomic ||
637 th->openupval == NULL || isintwups(th)); 623 th->openupval == NULL || isintwups(th));
638 for (; o < th->top.p; o++) /* mark live elements in the stack */ 624 for (; o < th->top.p; o++) /* mark live elements in the stack */
@@ -650,34 +636,35 @@ static int traversethread (global_State *g, lua_State *th) {
650 g->twups = th; 636 g->twups = th;
651 } 637 }
652 } 638 }
653 return 1 + stacksize(th);
654} 639}
655 640
656 641
657/* 642/*
658** traverse one gray object, turning it to black. 643** traverse one gray object, turning it to black.
659*/ 644*/
660static lu_mem propagatemark (global_State *g) { 645static void propagatemark (global_State *g) {
661 GCObject *o = g->gray; 646 GCObject *o = g->gray;
662 nw2black(o); 647 nw2black(o);
663 g->gray = *getgclist(o); /* remove from 'gray' list */ 648 g->gray = *getgclist(o); /* remove from 'gray' list */
664 switch (o->tt) { 649 switch (o->tt) {
665 case LUA_VTABLE: return traversetable(g, gco2t(o)); 650 case LUA_VTABLE: traversetable(g, gco2t(o)); break;
666 case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); 651 case LUA_VUSERDATA: traverseudata(g, gco2u(o)); break;
667 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); 652 case LUA_VLCL: traverseLclosure(g, gco2lcl(o)); break;
668 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); 653 case LUA_VCCL: traverseCclosure(g, gco2ccl(o)); break;
669 case LUA_VPROTO: return traverseproto(g, gco2p(o)); 654 case LUA_VPROTO: traverseproto(g, gco2p(o)); break;
670 case LUA_VTHREAD: return traversethread(g, gco2th(o)); 655 case LUA_VTHREAD: traversethread(g, gco2th(o)); break;
671 default: lua_assert(0); return 0; 656 default: lua_assert(0);
672 } 657 }
673} 658}
674 659
675 660
676static lu_mem propagateall (global_State *g) { 661static l_obj propagateall (global_State *g) {
677 lu_mem tot = 0; 662 l_obj work = 0;
678 while (g->gray) 663 while (g->gray) {
679 tot += propagatemark(g); 664 propagatemark(g);
680 return tot; 665 work++;
666 }
667 return work;
681} 668}
682 669
683 670
@@ -686,10 +673,10 @@ static lu_mem propagateall (global_State *g) {
686** Repeat until it converges, that is, nothing new is marked. 'dir' 673** Repeat until it converges, that is, nothing new is marked. 'dir'
687** inverts the direction of the traversals, trying to speed up 674** inverts the direction of the traversals, trying to speed up
688** convergence on chains in the same table. 675** convergence on chains in the same table.
689**
690*/ 676*/
691static void convergeephemerons (global_State *g) { 677static l_obj convergeephemerons (global_State *g) {
692 int changed; 678 int changed;
679 l_obj work = 0;
693 int dir = 0; 680 int dir = 0;
694 do { 681 do {
695 GCObject *w; 682 GCObject *w;
@@ -704,9 +691,11 @@ static void convergeephemerons (global_State *g) {
704 propagateall(g); /* propagate changes */ 691 propagateall(g); /* propagate changes */
705 changed = 1; /* will have to revisit all ephemeron tables */ 692 changed = 1; /* will have to revisit all ephemeron tables */
706 } 693 }
694 work++;
707 } 695 }
708 dir = !dir; /* invert direction next time */ 696 dir = !dir; /* invert direction next time */
709 } while (changed); /* repeat until no more changes */ 697 } while (changed); /* repeat until no more changes */
698 return work;
710} 699}
711 700
712/* }====================================================== */ 701/* }====================================================== */
@@ -722,7 +711,8 @@ static void convergeephemerons (global_State *g) {
722/* 711/*
723** clear entries with unmarked keys from all weaktables in list 'l' 712** clear entries with unmarked keys from all weaktables in list 'l'
724*/ 713*/
725static void clearbykeys (global_State *g, GCObject *l) { 714static l_obj clearbykeys (global_State *g, GCObject *l) {
715 l_obj work = 0;
726 for (; l; l = gco2t(l)->gclist) { 716 for (; l; l = gco2t(l)->gclist) {
727 Table *h = gco2t(l); 717 Table *h = gco2t(l);
728 Node *limit = gnodelast(h); 718 Node *limit = gnodelast(h);
@@ -733,7 +723,9 @@ static void clearbykeys (global_State *g, GCObject *l) {
733 if (isempty(gval(n))) /* is entry empty? */ 723 if (isempty(gval(n))) /* is entry empty? */
734 clearkey(n); /* clear its key */ 724 clearkey(n); /* clear its key */
735 } 725 }
726 work++;
736 } 727 }
728 return work;
737} 729}
738 730
739 731
@@ -741,7 +733,8 @@ static void clearbykeys (global_State *g, GCObject *l) {
741** clear entries with unmarked values from all weaktables in list 'l' up 733** clear entries with unmarked values from all weaktables in list 'l' up
742** to element 'f' 734** to element 'f'
743*/ 735*/
744static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { 736static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
737 l_obj work = 0;
745 for (; l != f; l = gco2t(l)->gclist) { 738 for (; l != f; l = gco2t(l)->gclist) {
746 Table *h = gco2t(l); 739 Table *h = gco2t(l);
747 Node *n, *limit = gnodelast(h); 740 Node *n, *limit = gnodelast(h);
@@ -758,7 +751,9 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
758 if (isempty(gval(n))) /* is entry empty? */ 751 if (isempty(gval(n))) /* is entry empty? */
759 clearkey(n); /* clear its key */ 752 clearkey(n); /* clear its key */
760 } 753 }
754 work++;
761 } 755 }
756 return work;
762} 757}
763 758
764 759
@@ -770,6 +765,7 @@ static void freeupval (lua_State *L, UpVal *uv) {
770 765
771 766
772static void freeobj (lua_State *L, GCObject *o) { 767static void freeobj (lua_State *L, GCObject *o) {
768 G(L)->totalobjs--;
773 switch (o->tt) { 769 switch (o->tt) {
774 case LUA_VPROTO: 770 case LUA_VPROTO:
775 luaF_freeproto(L, gco2p(o)); 771 luaF_freeproto(L, gco2p(o));
@@ -819,10 +815,9 @@ static void freeobj (lua_State *L, GCObject *o) {
819** objects, where a dead object is one marked with the old (non current) 815** objects, where a dead object is one marked with the old (non current)
820** white; change all non-dead objects back to white, preparing for next 816** white; change all non-dead objects back to white, preparing for next
821** collection cycle. Return where to continue the traversal or NULL if 817** collection cycle. Return where to continue the traversal or NULL if
822** list is finished. ('*countout' gets the number of elements traversed.) 818** list is finished.
823*/ 819*/
824static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, 820static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) {
825 int *countout) {
826 global_State *g = G(L); 821 global_State *g = G(L);
827 int ow = otherwhite(g); 822 int ow = otherwhite(g);
828 int i; 823 int i;
@@ -839,8 +834,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
839 p = &curr->next; /* go to next element */ 834 p = &curr->next; /* go to next element */
840 } 835 }
841 } 836 }
842 if (countout)
843 *countout = i; /* number of elements traversed */
844 return (*p == NULL) ? NULL : p; 837 return (*p == NULL) ? NULL : p;
845} 838}
846 839
@@ -851,7 +844,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
851static GCObject **sweeptolive (lua_State *L, GCObject **p) { 844static GCObject **sweeptolive (lua_State *L, GCObject **p) {
852 GCObject **old = p; 845 GCObject **old = p;
853 do { 846 do {
854 p = sweeplist(L, p, 1, NULL); 847 p = sweeplist(L, p, 1);
855 } while (p == old); 848 } while (p == old);
856 return p; 849 return p;
857} 850}
@@ -870,11 +863,8 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) {
870*/ 863*/
871static void checkSizes (lua_State *L, global_State *g) { 864static void checkSizes (lua_State *L, global_State *g) {
872 if (!g->gcemergency) { 865 if (!g->gcemergency) {
873 if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ 866 if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
874 l_mem olddebt = g->GCdebt;
875 luaS_resize(L, g->strt.size / 2); 867 luaS_resize(L, g->strt.size / 2);
876 g->GCestimate += g->GCdebt - olddebt; /* correct estimate */
877 }
878 } 868 }
879} 869}
880 870
@@ -933,18 +923,6 @@ static void GCTM (lua_State *L) {
933 923
934 924
935/* 925/*
936** Call a few finalizers
937*/
938static int runafewfinalizers (lua_State *L, int n) {
939 global_State *g = G(L);
940 int i;
941 for (i = 0; i < n && g->tobefnz; i++)
942 GCTM(L); /* call one finalizer */
943 return i;
944}
945
946
947/*
948** call all pending finalizers 926** call all pending finalizers
949*/ 927*/
950static void callallpendingfinalizers (lua_State *L) { 928static void callallpendingfinalizers (lua_State *L) {
@@ -1052,20 +1030,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
1052 1030
1053/* 1031/*
1054** Set the "time" to wait before starting a new GC cycle; cycle will 1032** Set the "time" to wait before starting a new GC cycle; cycle will
1055** start when memory use hits the threshold of ('estimate' * pause / 1033** start when number of objects in use hits the threshold of
1056** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, 1034** approximately (marked * pause / 100).
1057** because Lua cannot even start with less than PAUSEADJ bytes).
1058*/ 1035*/
1059static void setpause (global_State *g) { 1036static void setpause (global_State *g) {
1060 l_mem threshold, debt; 1037 l_obj threshold = applygcparam(g, gcpause, g->marked);
1061 int pause = getgcparam(g->gcpause); 1038 l_obj debt = threshold - gettotalobjs(g);
1062 l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ 1039 if (debt < 0) debt = 0;
1063 lua_assert(estimate > 0);
1064 threshold = (pause < MAX_LMEM / estimate) /* overflow? */
1065 ? estimate * pause /* no overflow */
1066 : MAX_LMEM; /* overflow; truncate to maximum */
1067 debt = gettotalbytes(g) - threshold;
1068 if (debt > 0) debt = 0;
1069 luaE_setdebt(g, debt); 1040 luaE_setdebt(g, debt);
1070} 1041}
1071 1042
@@ -1305,18 +1276,17 @@ static void atomic2gen (lua_State *L, global_State *g) {
1305 sweep2old(L, &g->tobefnz); 1276 sweep2old(L, &g->tobefnz);
1306 1277
1307 g->gckind = KGC_GEN; 1278 g->gckind = KGC_GEN;
1308 g->lastatomic = 0; 1279 g->GClastmajor = gettotalobjs(g); /* base for memory control */
1309 g->GCestimate = gettotalbytes(g); /* base for memory control */
1310 finishgencycle(L, g); 1280 finishgencycle(L, g);
1311} 1281}
1312 1282
1313 1283
1314/* 1284/*
1315** Set debt for the next minor collection, which will happen when 1285** Set debt for the next minor collection, which will happen when
1316** memory grows 'genminormul'%. 1286** total number of objects grows 'genminormul'%.
1317*/ 1287*/
1318static void setminordebt (global_State *g) { 1288static void setminordebt (global_State *g) {
1319 luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); 1289 luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g)));
1320} 1290}
1321 1291
1322 1292
@@ -1326,14 +1296,12 @@ static void setminordebt (global_State *g) {
1326** are cleared. Then, turn all objects into old and finishes the 1296** are cleared. Then, turn all objects into old and finishes the
1327** collection. 1297** collection.
1328*/ 1298*/
1329static lu_mem entergen (lua_State *L, global_State *g) { 1299static void entergen (lua_State *L, global_State *g) {
1330 lu_mem numobjs;
1331 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ 1300 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */
1332 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1301 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1333 numobjs = atomic(L); /* propagates all and then do the atomic stuff */ 1302 atomic(L); /* propagates all and then do the atomic stuff */
1334 atomic2gen(L, g); 1303 atomic2gen(L, g);
1335 setminordebt(g); /* set debt assuming next cycle will be minor */ 1304 setminordebt(g); /* set debt assuming next cycle will be minor */
1336 return numobjs;
1337} 1305}
1338 1306
1339 1307
@@ -1350,7 +1318,6 @@ static void enterinc (global_State *g) {
1350 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1318 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1351 g->gcstate = GCSpause; 1319 g->gcstate = GCSpause;
1352 g->gckind = KGC_INC; 1320 g->gckind = KGC_INC;
1353 g->lastatomic = 0;
1354} 1321}
1355 1322
1356 1323
@@ -1359,111 +1326,75 @@ static void enterinc (global_State *g) {
1359*/ 1326*/
1360void luaC_changemode (lua_State *L, int newmode) { 1327void luaC_changemode (lua_State *L, int newmode) {
1361 global_State *g = G(L); 1328 global_State *g = G(L);
1362 if (newmode != g->gckind) { 1329 if (newmode != g->gckind) { /* does it need to change? */
1363 if (newmode == KGC_GEN) /* entering generational mode? */ 1330 if (newmode == KGC_INC) { /* entering incremental mode? */
1331 if (g->gckind == KGC_GENMAJOR)
1332 g->gckind = KGC_INC; /* already incremental but in name */
1333 else
1334 enterinc(g); /* entering incremental mode */
1335 }
1336 else {
1337 lua_assert(newmode == KGC_GEN);
1364 entergen(L, g); 1338 entergen(L, g);
1365 else 1339 }
1366 enterinc(g); /* entering incremental mode */
1367 } 1340 }
1368 g->lastatomic = 0;
1369} 1341}
1370 1342
1371 1343
1372/* 1344/*
1373** Does a full collection in generational mode. 1345** Does a full collection in generational mode.
1374*/ 1346*/
1375static lu_mem fullgen (lua_State *L, global_State *g) { 1347static void fullgen (lua_State *L, global_State *g) {
1376 enterinc(g); 1348 enterinc(g);
1377 return entergen(L, g); 1349 entergen(L, g);
1378} 1350}
1379 1351
1380 1352
1381/* 1353/*
1382** Does a major collection after last collection was a "bad collection". 1354** Does a major collector up to the atomic phase and then either
1383** 1355** returns to minor collections or stays doing major ones. If the
1384** When the program is building a big structure, it allocates lots of 1356** number of objects collected this time (numobjs - marked) is more than
1385** memory but generates very little garbage. In those scenarios, 1357** half the number of objects created since the last major collection
1386** the generational mode just wastes time doing small collections, and 1358** (numobjs - lastmajor), it goes back to minor collections.
1387** major collections are frequently what we call a "bad collection", a 1359*/
1388** collection that frees too few objects. To avoid the cost of switching 1360static void genmajorstep (lua_State *L, global_State *g) {
1389** between generational mode and the incremental mode needed for full 1361 l_obj lastmajor = g->GClastmajor; /* count from last collection */
1390** (major) collections, the collector tries to stay in incremental mode 1362 l_obj numobjs = gettotalobjs(g); /* current count */
1391** after a bad collection, and to switch back to generational mode only
1392** after a "good" collection (one that traverses less than 9/8 objects
1393** of the previous one).
1394** The collector must choose whether to stay in incremental mode or to
1395** switch back to generational mode before sweeping. At this point, it
1396** does not know the real memory in use, so it cannot use memory to
1397** decide whether to return to generational mode. Instead, it uses the
1398** number of objects traversed (returned by 'atomic') as a proxy. The
1399** field 'g->lastatomic' keeps this count from the last collection.
1400** ('g->lastatomic != 0' also means that the last collection was bad.)
1401*/
1402static void stepgenfull (lua_State *L, global_State *g) {
1403 lu_mem newatomic; /* count of traversed objects */
1404 lu_mem lastatomic = g->lastatomic; /* count from last collection */
1405 if (g->gckind == KGC_GEN) /* still in generational mode? */
1406 enterinc(g); /* enter incremental mode */
1407 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1363 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1408 newatomic = atomic(L); /* mark everybody */ 1364 atomic(L); /* mark everybody */
1409 if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ 1365 if ((numobjs - g->marked) > ((numobjs - lastmajor) >> 1)) {
1410 atomic2gen(L, g); /* return to generational mode */ 1366 atomic2gen(L, g); /* return to generational mode */
1411 setminordebt(g); 1367 setminordebt(g);
1412 } 1368 }
1413 else { /* another bad collection; stay in incremental mode */ 1369 else { /* bad collection; stay in major mode */
1414 g->GCestimate = gettotalbytes(g); /* first estimate */
1415 entersweep(L); 1370 entersweep(L);
1416 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1371 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1417 setpause(g); 1372 setpause(g);
1418 g->lastatomic = newatomic; 1373 g->GClastmajor = gettotalobjs(g);
1419 } 1374 }
1420} 1375}
1421 1376
1422 1377
1423/* 1378/*
1424** Does a generational "step". 1379** Does a generational "step". If the total number of objects grew
1425** Usually, this means doing a minor collection and setting the debt to 1380** more than 'majormul'% since the last major collection, does a
1426** make another collection when memory grows 'genminormul'% larger. 1381** major collection. Otherwise, does a minor collection.
1427**
1428** However, there are exceptions. If memory grows 'genmajormul'%
1429** larger than it was at the end of the last major collection (kept
1430** in 'g->GCestimate'), the function does a major collection. At the
1431** end, it checks whether the major collection was able to free a
1432** decent amount of memory (at least half the growth in memory since
1433** previous major collection). If so, the collector keeps its state,
1434** and the next collection will probably be minor again. Otherwise,
1435** we have what we call a "bad collection". In that case, set the field
1436** 'g->lastatomic' to signal that fact, so that the next collection will
1437** go to 'stepgenfull'.
1438**
1439** 'GCdebt <= 0' means an explicit call to GC step with "size" zero;
1440** in that case, do a minor collection.
1441*/ 1382*/
1442static void genstep (lua_State *L, global_State *g) { 1383static void genstep (lua_State *L, global_State *g) {
1443 if (g->lastatomic != 0) /* last collection was a bad one? */ 1384 l_obj majorbase = g->GClastmajor; /* count after last major collection */
1444 stepgenfull(L, g); /* do a full step */ 1385 l_obj majorinc = applygcparam(g, genmajormul, majorbase);
1445 else { 1386 if (gettotalobjs(g) > majorbase + majorinc && 0) {
1446 lu_mem majorbase = g->GCestimate; /* memory after last major collection */ 1387 /* do a major collection */
1447 lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); 1388 enterinc(g);
1448 if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { 1389 g->gckind = KGC_GENMAJOR;
1449 lu_mem numobjs = fullgen(L, g); /* do a major collection */ 1390 genmajorstep(L, g);
1450 if (gettotalbytes(g) < majorbase + (majorinc / 2)) { 1391 }
1451 /* collected at least half of memory growth since last major 1392 else { /* regular case; do a minor collection */
1452 collection; keep doing minor collections. */ 1393 g->marked = 0;
1453 lua_assert(g->lastatomic == 0); 1394 youngcollection(L, g);
1454 } 1395 setminordebt(g);
1455 else { /* bad collection */ 1396 lua_assert(g->GClastmajor == majorbase);
1456 g->lastatomic = numobjs; /* signal that last collection was bad */
1457 setpause(g); /* do a long wait for next (major) collection */
1458 }
1459 }
1460 else { /* regular case; do a minor collection */
1461 youngcollection(L, g);
1462 setminordebt(g);
1463 g->GCestimate = majorbase; /* preserve base value */
1464 }
1465 } 1397 }
1466 lua_assert(isdecGCmodegen(g));
1467} 1398}
1468 1399
1469/* }====================================================== */ 1400/* }====================================================== */
@@ -1522,9 +1453,9 @@ void luaC_freeallobjects (lua_State *L) {
1522} 1453}
1523 1454
1524 1455
1525static lu_mem atomic (lua_State *L) { 1456static l_obj atomic (lua_State *L) {
1457 l_obj work = 0;
1526 global_State *g = G(L); 1458 global_State *g = G(L);
1527 lu_mem work = 0;
1528 GCObject *origweak, *origall; 1459 GCObject *origweak, *origall;
1529 GCObject *grayagain = g->grayagain; /* save original list */ 1460 GCObject *grayagain = g->grayagain; /* save original list */
1530 g->grayagain = NULL; 1461 g->grayagain = NULL;
@@ -1541,50 +1472,44 @@ static lu_mem atomic (lua_State *L) {
1541 work += propagateall(g); /* propagate changes */ 1472 work += propagateall(g); /* propagate changes */
1542 g->gray = grayagain; 1473 g->gray = grayagain;
1543 work += propagateall(g); /* traverse 'grayagain' list */ 1474 work += propagateall(g); /* traverse 'grayagain' list */
1544 convergeephemerons(g); 1475 work += convergeephemerons(g);
1545 /* at this point, all strongly accessible objects are marked. */ 1476 /* at this point, all strongly accessible objects are marked. */
1546 /* Clear values from weak tables, before checking finalizers */ 1477 /* Clear values from weak tables, before checking finalizers */
1547 clearbyvalues(g, g->weak, NULL); 1478 work += clearbyvalues(g, g->weak, NULL);
1548 clearbyvalues(g, g->allweak, NULL); 1479 work += clearbyvalues(g, g->allweak, NULL);
1549 origweak = g->weak; origall = g->allweak; 1480 origweak = g->weak; origall = g->allweak;
1550 separatetobefnz(g, 0); /* separate objects to be finalized */ 1481 separatetobefnz(g, 0); /* separate objects to be finalized */
1551 work += markbeingfnz(g); /* mark objects that will be finalized */ 1482 work += markbeingfnz(g); /* mark objects that will be finalized */
1552 work += propagateall(g); /* remark, to propagate 'resurrection' */ 1483 work += propagateall(g); /* remark, to propagate 'resurrection' */
1553 convergeephemerons(g); 1484 work += convergeephemerons(g);
1554 /* at this point, all resurrected objects are marked. */ 1485 /* at this point, all resurrected objects are marked. */
1555 /* remove dead objects from weak tables */ 1486 /* remove dead objects from weak tables */
1556 clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ 1487 work += clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */
1557 clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ 1488 work += clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */
1558 /* clear values from resurrected weak tables */ 1489 /* clear values from resurrected weak tables */
1559 clearbyvalues(g, g->weak, origweak); 1490 work += clearbyvalues(g, g->weak, origweak);
1560 clearbyvalues(g, g->allweak, origall); 1491 work += clearbyvalues(g, g->allweak, origall);
1561 luaS_clearcache(g); 1492 luaS_clearcache(g);
1562 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1493 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
1563 lua_assert(g->gray == NULL); 1494 lua_assert(g->gray == NULL);
1564 return work; /* estimate of slots marked by 'atomic' */ 1495 return work;
1565} 1496}
1566 1497
1567 1498
1568static int sweepstep (lua_State *L, global_State *g, 1499static void sweepstep (lua_State *L, global_State *g,
1569 int nextstate, GCObject **nextlist) { 1500 int nextstate, GCObject **nextlist) {
1570 if (g->sweepgc) { 1501 if (g->sweepgc)
1571 l_mem olddebt = g->GCdebt; 1502 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
1572 int count;
1573 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count);
1574 g->GCestimate += g->GCdebt - olddebt; /* update estimate */
1575 return count;
1576 }
1577 else { /* enter next state */ 1503 else { /* enter next state */
1578 g->gcstate = nextstate; 1504 g->gcstate = nextstate;
1579 g->sweepgc = nextlist; 1505 g->sweepgc = nextlist;
1580 return 0; /* no work done */
1581 } 1506 }
1582} 1507}
1583 1508
1584 1509
1585static lu_mem singlestep (lua_State *L) { 1510static l_obj singlestep (lua_State *L) {
1586 global_State *g = G(L); 1511 global_State *g = G(L);
1587 lu_mem work; 1512 l_obj work;
1588 lua_assert(!g->gcstopem); /* collector is not reentrant */ 1513 lua_assert(!g->gcstopem); /* collector is not reentrant */
1589 g->gcstopem = 1; /* no emergency collections while collecting */ 1514 g->gcstopem = 1; /* no emergency collections while collecting */
1590 switch (g->gcstate) { 1515 switch (g->gcstate) {
@@ -1599,26 +1524,30 @@ static lu_mem singlestep (lua_State *L) {
1599 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1524 g->gcstate = GCSenteratomic; /* finish propagate phase */
1600 work = 0; 1525 work = 0;
1601 } 1526 }
1602 else 1527 else {
1603 work = propagatemark(g); /* traverse one gray object */ 1528 propagatemark(g); /* traverse one gray object */
1529 work = 1;
1530 }
1604 break; 1531 break;
1605 } 1532 }
1606 case GCSenteratomic: { 1533 case GCSenteratomic: {
1607 work = atomic(L); /* work is what was traversed by 'atomic' */ 1534 work = atomic(L);
1608 entersweep(L); 1535 entersweep(L);
1609 g->GCestimate = gettotalbytes(g); /* first estimate */
1610 break; 1536 break;
1611 } 1537 }
1612 case GCSswpallgc: { /* sweep "regular" objects */ 1538 case GCSswpallgc: { /* sweep "regular" objects */
1613 work = sweepstep(L, g, GCSswpfinobj, &g->finobj); 1539 sweepstep(L, g, GCSswpfinobj, &g->finobj);
1540 work = GCSWEEPMAX;
1614 break; 1541 break;
1615 } 1542 }
1616 case GCSswpfinobj: { /* sweep objects with finalizers */ 1543 case GCSswpfinobj: { /* sweep objects with finalizers */
1617 work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1544 sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1545 work = GCSWEEPMAX;
1618 break; 1546 break;
1619 } 1547 }
1620 case GCSswptobefnz: { /* sweep objects to be finalized */ 1548 case GCSswptobefnz: { /* sweep objects to be finalized */
1621 work = sweepstep(L, g, GCSswpend, NULL); 1549 sweepstep(L, g, GCSswpend, NULL);
1550 work = GCSWEEPMAX;
1622 break; 1551 break;
1623 } 1552 }
1624 case GCSswpend: { /* finish sweeps */ 1553 case GCSswpend: { /* finish sweeps */
@@ -1627,10 +1556,11 @@ static lu_mem singlestep (lua_State *L) {
1627 work = 0; 1556 work = 0;
1628 break; 1557 break;
1629 } 1558 }
1630 case GCScallfin: { /* call remaining finalizers */ 1559 case GCScallfin: { /* call finalizers */
1631 if (g->tobefnz && !g->gcemergency) { 1560 if (g->tobefnz && !g->gcemergency) {
1632 g->gcstopem = 0; /* ok collections during finalizers */ 1561 g->gcstopem = 0; /* ok collections during finalizers */
1633 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; 1562 GCTM(L); /* call one finalizer */
1563 work = 1;
1634 } 1564 }
1635 else { /* emergency mode or no more finalizers */ 1565 else { /* emergency mode or no more finalizers */
1636 g->gcstate = GCSpause; /* finish collection */ 1566 g->gcstate = GCSpause; /* finish collection */
@@ -1665,20 +1595,16 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1665** controls when next step will be performed. 1595** controls when next step will be performed.
1666*/ 1596*/
1667static void incstep (lua_State *L, global_State *g) { 1597static void incstep (lua_State *L, global_State *g) {
1668 int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ 1598 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1669 l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; 1599 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1670 l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem))
1671 ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul
1672 : MAX_LMEM; /* overflow; keep maximum value */
1673 do { /* repeat until pause or enough "credit" (negative debt) */ 1600 do { /* repeat until pause or enough "credit" (negative debt) */
1674 lu_mem work = singlestep(L); /* perform one single step */ 1601 l_obj work = singlestep(L); /* perform one single step */
1675 debt -= work; 1602 work2do -= work;
1676 } while (debt > -stepsize && g->gcstate != GCSpause); 1603 } while (work2do > 0 && g->gcstate != GCSpause);
1677 if (g->gcstate == GCSpause) 1604 if (g->gcstate == GCSpause)
1678 setpause(g); /* pause until next cycle */ 1605 setpause(g); /* pause until next cycle */
1679 else { 1606 else {
1680 debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ 1607 luaE_setdebt(g, stepsize);
1681 luaE_setdebt(g, debt);
1682 } 1608 }
1683} 1609}
1684 1610
@@ -1689,13 +1615,21 @@ static void incstep (lua_State *L, global_State *g) {
1689*/ 1615*/
1690void luaC_step (lua_State *L) { 1616void luaC_step (lua_State *L) {
1691 global_State *g = G(L); 1617 global_State *g = G(L);
1618 lua_assert(!g->gcemergency);
1692 if (!gcrunning(g)) /* not running? */ 1619 if (!gcrunning(g)) /* not running? */
1693 luaE_setdebt(g, -2000); 1620 luaE_setdebt(g, 2000);
1694 else { 1621 else {
1695 if(isdecGCmodegen(g)) 1622 switch (g->gckind) {
1696 genstep(L, g); 1623 case KGC_INC:
1697 else 1624 incstep(L, g);
1698 incstep(L, g); 1625 break;
1626 case KGC_GEN:
1627 genstep(L, g);
1628 break;
1629 case KGC_GENMAJOR:
1630 genmajorstep(L, g);
1631 break;
1632 }
1699 } 1633 }
1700} 1634}
1701 1635
@@ -1715,8 +1649,8 @@ static void fullinc (lua_State *L, global_State *g) {
1715 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1649 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1716 g->gcstate = GCSenteratomic; /* go straight to atomic phase ??? */ 1650 g->gcstate = GCSenteratomic; /* go straight to atomic phase ??? */
1717 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ 1651 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1718 /* estimate must be correct after a full GC cycle */ 1652 /* 'marked' must be correct after a full GC cycle */
1719 lua_assert(g->GCestimate == gettotalbytes(g)); 1653 lua_assert(g->marked == gettotalobjs(g));
1720 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1654 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1721 setpause(g); 1655 setpause(g);
1722} 1656}
@@ -1731,10 +1665,10 @@ void luaC_fullgc (lua_State *L, int isemergency) {
1731 global_State *g = G(L); 1665 global_State *g = G(L);
1732 lua_assert(!g->gcemergency); 1666 lua_assert(!g->gcemergency);
1733 g->gcemergency = isemergency; /* set flag */ 1667 g->gcemergency = isemergency; /* set flag */
1734 if (g->gckind == KGC_INC) 1668 if (g->gckind == KGC_GEN)
1735 fullinc(L, g);
1736 else
1737 fullgen(L, g); 1669 fullgen(L, g);
1670 else
1671 fullinc(L, g);
1738 g->gcemergency = 0; 1672 g->gcemergency = 0;
1739} 1673}
1740 1674
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 980e42f8..209a87fc 100644
--- a/lobject.h
+++ b/lobject.h
@@ -392,7 +392,7 @@ typedef struct TString {
392 size_t lnglen; /* length for long strings */ 392 size_t lnglen; /* length for long strings */
393 struct TString *hnext; /* linked list for hash table */ 393 struct TString *hnext; /* linked list for hash table */
394 } u; 394 } u;
395 char contents[1]; 395 char contents[1]; /* string body starts here */
396} TString; 396} TString;
397 397
398 398
@@ -401,15 +401,22 @@ typedef struct TString {
401** Get the actual string (array of bytes) from a 'TString'. (Generic 401** Get the actual string (array of bytes) from a 'TString'. (Generic
402** version and specialized versions for long and short strings.) 402** version and specialized versions for long and short strings.)
403*/ 403*/
404#define getstr(ts) ((ts)->contents)
405#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents) 404#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents)
406#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents) 405#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents)
406#define getstr(ts) ((ts)->contents)
407 407
408 408
409/* get string length from 'TString *s' */ 409/* get string length from 'TString *s' */
410#define tsslen(s) \ 410#define tsslen(s) \
411 ((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen) 411 ((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen)
412 412
413/*
414** Get string and length */
415#define getlstr(ts, len) \
416 ((ts)->shrlen != 0xFF \
417 ? (cast_void(len = (ts)->shrlen), (ts)->contents) \
418 : (cast_void(len = (ts)->u.lnglen), (ts)->contents))
419
413/* }================================================================== */ 420/* }================================================================== */
414 421
415 422
@@ -544,13 +551,21 @@ typedef struct AbsLineInfo {
544 int line; 551 int line;
545} AbsLineInfo; 552} AbsLineInfo;
546 553
554
555/*
556** Flags in Prototypes
557*/
558#define PF_ISVARARG 1
559#define PF_FIXED 2 /* prototype has parts in fixed memory */
560
561
547/* 562/*
548** Function Prototypes 563** Function Prototypes
549*/ 564*/
550typedef struct Proto { 565typedef struct Proto {
551 CommonHeader; 566 CommonHeader;
552 lu_byte numparams; /* number of fixed (named) parameters */ 567 lu_byte numparams; /* number of fixed (named) parameters */
553 lu_byte is_vararg; 568 lu_byte flag;
554 lu_byte maxstacksize; /* number of registers needed by this function */ 569 lu_byte maxstacksize; /* number of registers needed by this function */
555 int sizeupvalues; /* size of 'upvalues' */ 570 int sizeupvalues; /* size of 'upvalues' */
556 int sizek; /* size of 'k' */ 571 int sizek; /* size of 'k' */
@@ -741,7 +756,6 @@ typedef struct Table {
741 unsigned int alimit; /* "limit" of 'array' array */ 756 unsigned int alimit; /* "limit" of 'array' array */
742 TValue *array; /* array part */ 757 TValue *array; /* array part */
743 Node *node; 758 Node *node;
744 Node *lastfree; /* any free position is before this position */
745 struct Table *metatable; 759 struct Table *metatable;
746 GCObject *gclist; 760 GCObject *gclist;
747} Table; 761} 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 7fefacba..6f4c7e28 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
@@ -278,7 +247,8 @@ static void close_state (lua_State *L) {
278 } 247 }
279 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); 248 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
280 freestack(L); 249 freestack(L);
281 lua_assert(gettotalbytes(g) == sizeof(LG)); 250 lua_assert(g->totalbytes == sizeof(LG));
251 lua_assert(gettotalobjs(g) == 1);
282 (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ 252 (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
283} 253}
284 254
@@ -349,15 +319,7 @@ LUA_API int lua_closethread (lua_State *L, lua_State *from) {
349} 319}
350 320
351 321
352/* 322LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
353** Deprecated! Use 'lua_closethread' instead.
354*/
355LUA_API int lua_resetthread (lua_State *L) {
356 return lua_closethread(L, NULL);
357}
358
359
360LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
361 int i; 323 int i;
362 lua_State *L; 324 lua_State *L;
363 global_State *g; 325 global_State *g;
@@ -377,7 +339,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
377 g->warnf = NULL; 339 g->warnf = NULL;
378 g->ud_warn = NULL; 340 g->ud_warn = NULL;
379 g->mainthread = L; 341 g->mainthread = L;
380 g->seed = luai_makeseed(L); 342 g->seed = seed;
381 g->gcstp = GCSTPGC; /* no GC while building state */ 343 g->gcstp = GCSTPGC; /* no GC while building state */
382 g->strt.size = g->strt.nuse = 0; 344 g->strt.size = g->strt.nuse = 0;
383 g->strt.hash = NULL; 345 g->strt.hash = NULL;
@@ -395,14 +357,15 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
395 g->weak = g->ephemeron = g->allweak = NULL; 357 g->weak = g->ephemeron = g->allweak = NULL;
396 g->twups = NULL; 358 g->twups = NULL;
397 g->totalbytes = sizeof(LG); 359 g->totalbytes = sizeof(LG);
360 g->totalobjs = 1;
361 g->marked = 0;
398 g->GCdebt = 0; 362 g->GCdebt = 0;
399 g->lastatomic = 0;
400 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ 363 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
401 setgcparam(g->gcpause, LUAI_GCPAUSE); 364 setgcparam(g, gcpause, LUAI_GCPAUSE);
402 setgcparam(g->gcstepmul, LUAI_GCMUL); 365 setgcparam(g, gcstepmul, LUAI_GCMUL);
403 g->gcstepsize = LUAI_GCSTEPSIZE; 366 g->gcstepsize = LUAI_GCSTEPSIZE;
404 setgcparam(g->genmajormul, LUAI_GENMAJORMUL); 367 setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
405 g->genminormul = LUAI_GENMINORMUL; 368 setgcparam(g, genminormul, LUAI_GENMINORMUL);
406 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 369 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
407 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 370 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
408 /* memory allocation error: free partial state */ 371 /* 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 3353c047..103478fb 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*/
@@ -369,8 +390,15 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
369 390
370 391
371static void freehash (lua_State *L, Table *t) { 392static void freehash (lua_State *L, Table *t) {
372 if (!isdummy(t)) 393 if (!isdummy(t)) {
373 luaM_freearray(L, t->node, cast_sizet(sizenode(t))); 394 size_t bsize = sizenode(t) * sizeof(Node); /* 'node' size in bytes */
395 char *arr = cast_charp(t->node);
396 if (haslastfree(t)) {
397 bsize += sizeof(Limbox);
398 arr -= sizeof(Limbox);
399 }
400 luaM_freearray(L, arr, bsize);
401 }
374} 402}
375 403
376 404
@@ -481,7 +509,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
481 if (size == 0) { /* no elements to hash part? */ 509 if (size == 0) { /* no elements to hash part? */
482 t->node = cast(Node *, dummynode); /* use common 'dummynode' */ 510 t->node = cast(Node *, dummynode); /* use common 'dummynode' */
483 t->lsizenode = 0; 511 t->lsizenode = 0;
484 t->lastfree = NULL; /* signal that it is using dummy node */ 512 setdummy(t); /* signal that it is using dummy node */
485 } 513 }
486 else { 514 else {
487 int i; 515 int i;
@@ -489,15 +517,22 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
489 if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) 517 if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE)
490 luaG_runerror(L, "table overflow"); 518 luaG_runerror(L, "table overflow");
491 size = twoto(lsize); 519 size = twoto(lsize);
492 t->node = luaM_newvector(L, size, Node); 520 if (lsize <= LLIMFORLAST) /* no 'lastfree' field? */
521 t->node = luaM_newvector(L, size, Node);
522 else {
523 size_t bsize = size * sizeof(Node) + sizeof(Limbox);
524 char *node = luaM_newblock(L, bsize);
525 t->node = cast(Node *, node + sizeof(Limbox));
526 *getlastfree(t) = size; /* all positions are free */
527 }
528 t->lsizenode = cast_byte(lsize);
529 setnodummy(t);
493 for (i = 0; i < cast_int(size); i++) { 530 for (i = 0; i < cast_int(size); i++) {
494 Node *n = gnode(t, i); 531 Node *n = gnode(t, i);
495 gnext(n) = 0; 532 gnext(n) = 0;
496 setnilkey(n); 533 setnilkey(n);
497 setempty(gval(n)); 534 setempty(gval(n));
498 } 535 }
499 t->lsizenode = cast_byte(lsize);
500 t->lastfree = gnode(t, size); /* all positions are free */
501 } 536 }
502} 537}
503 538
@@ -522,18 +557,21 @@ static void reinsert (lua_State *L, Table *ot, Table *t) {
522 557
523 558
524/* 559/*
525** Exchange the hash part of 't1' and 't2'. 560** Exchange the hash part of 't1' and 't2'. (In 'flags', only the
561** dummy bit must be exchanged: The 'isrealasize' is not related
562** to the hash part, and the metamethod bits do not change during
563** a resize, so the "real" table can keep their values.)
526*/ 564*/
527static void exchangehashpart (Table *t1, Table *t2) { 565static void exchangehashpart (Table *t1, Table *t2) {
528 lu_byte lsizenode = t1->lsizenode; 566 lu_byte lsizenode = t1->lsizenode;
529 Node *node = t1->node; 567 Node *node = t1->node;
530 Node *lastfree = t1->lastfree; 568 int bitdummy1 = t1->flags & BITDUMMY;
531 t1->lsizenode = t2->lsizenode; 569 t1->lsizenode = t2->lsizenode;
532 t1->node = t2->node; 570 t1->node = t2->node;
533 t1->lastfree = t2->lastfree; 571 t1->flags = (t1->flags & NOTBITDUMMY) | (t2->flags & BITDUMMY);
534 t2->lsizenode = lsizenode; 572 t2->lsizenode = lsizenode;
535 t2->node = node; 573 t2->node = node;
536 t2->lastfree = lastfree; 574 t2->flags = (t2->flags & NOTBITDUMMY) | bitdummy1;
537} 575}
538 576
539 577
@@ -557,6 +595,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
557 unsigned int oldasize = setlimittosize(t); 595 unsigned int oldasize = setlimittosize(t);
558 TValue *newarray; 596 TValue *newarray;
559 /* create new hash part with appropriate size into 'newt' */ 597 /* create new hash part with appropriate size into 'newt' */
598 newt.flags = 0;
560 setnodevector(L, &newt, nhsize); 599 setnodevector(L, &newt, nhsize);
561 if (newasize < oldasize) { /* will array shrink? */ 600 if (newasize < oldasize) { /* will array shrink? */
562 t->alimit = newasize; /* pretend array has new size... */ 601 t->alimit = newasize; /* pretend array has new size... */
@@ -643,11 +682,22 @@ void luaH_free (lua_State *L, Table *t) {
643 682
644 683
645static Node *getfreepos (Table *t) { 684static Node *getfreepos (Table *t) {
646 if (!isdummy(t)) { 685 if (haslastfree(t)) { /* does it have 'lastfree' information? */
647 while (t->lastfree > t->node) { 686 /* look for a spot before 'lastfree', updating 'lastfree' */
648 t->lastfree--; 687 while (*getlastfree(t) > 0) {
649 if (keyisnil(t->lastfree)) 688 Node *free = gnode(t, --(*getlastfree(t)));
650 return t->lastfree; 689 if (keyisnil(free))
690 return free;
691 }
692 }
693 else { /* no 'lastfree' information */
694 if (!isdummy(t)) {
695 int i = sizenode(t);
696 while (i--) { /* do a linear search */
697 Node *free = gnode(t, i);
698 if (keyisnil(free))
699 return free;
700 }
651 } 701 }
652 } 702 }
653 return NULL; /* could not find a free place */ 703 return NULL; /* could not find a free place */
diff --git a/ltable.h b/ltable.h
index 8e689034..30cfc8be 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 7d184c0d..15d1a564 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))
@@ -531,7 +531,7 @@ static void checkobject (global_State *g, GCObject *o, int maybedead,
531} 531}
532 532
533 533
534static lu_mem checkgraylist (global_State *g, GCObject *o) { 534static l_obj checkgraylist (global_State *g, GCObject *o) {
535 int total = 0; /* count number of elements in the list */ 535 int total = 0; /* count number of elements in the list */
536 cast_void(g); /* better to keep it if we need to print an object */ 536 cast_void(g); /* better to keep it if we need to print an object */
537 while (o) { 537 while (o) {
@@ -560,7 +560,7 @@ static lu_mem checkgraylist (global_State *g, GCObject *o) {
560/* 560/*
561** Check objects in gray lists. 561** Check objects in gray lists.
562*/ 562*/
563static lu_mem checkgrays (global_State *g) { 563static l_obj checkgrays (global_State *g) {
564 int total = 0; /* count number of elements in all lists */ 564 int total = 0; /* count number of elements in all lists */
565 if (!keepinvariant(g)) return total; 565 if (!keepinvariant(g)) return total;
566 total += checkgraylist(g, g->gray); 566 total += checkgraylist(g, g->gray);
@@ -577,7 +577,7 @@ static lu_mem checkgrays (global_State *g) {
577** 'count' and check its TESTBIT. (It must have been previously set by 577** 'count' and check its TESTBIT. (It must have been previously set by
578** 'checkgraylist'.) 578** 'checkgraylist'.)
579*/ 579*/
580static void incifingray (global_State *g, GCObject *o, lu_mem *count) { 580static void incifingray (global_State *g, GCObject *o, l_obj *count) {
581 if (!keepinvariant(g)) 581 if (!keepinvariant(g))
582 return; /* gray lists not being kept in these phases */ 582 return; /* gray lists not being kept in these phases */
583 if (o->tt == LUA_VUPVAL) { 583 if (o->tt == LUA_VUPVAL) {
@@ -594,10 +594,10 @@ static void incifingray (global_State *g, GCObject *o, lu_mem *count) {
594} 594}
595 595
596 596
597static lu_mem checklist (global_State *g, int maybedead, int tof, 597static l_obj checklist (global_State *g, int maybedead, int tof,
598 GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) { 598 GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) {
599 GCObject *o; 599 GCObject *o;
600 lu_mem total = 0; /* number of object that should be in gray lists */ 600 l_obj total = 0; /* number of object that should be in gray lists */
601 for (o = newl; o != survival; o = o->next) { 601 for (o = newl; o != survival; o = o->next) {
602 checkobject(g, o, maybedead, G_NEW); 602 checkobject(g, o, maybedead, G_NEW);
603 incifingray(g, o, &total); 603 incifingray(g, o, &total);
@@ -626,8 +626,8 @@ int lua_checkmemory (lua_State *L) {
626 global_State *g = G(L); 626 global_State *g = G(L);
627 GCObject *o; 627 GCObject *o;
628 int maybedead; 628 int maybedead;
629 lu_mem totalin; /* total of objects that are in gray lists */ 629 l_obj totalin; /* total of objects that are in gray lists */
630 lu_mem totalshould; /* total of objects that should be in gray lists */ 630 l_obj totalshould; /* total of objects that should be in gray lists */
631 if (keepinvariant(g)) { 631 if (keepinvariant(g)) {
632 assert(!iswhite(g->mainthread)); 632 assert(!iswhite(g->mainthread));
633 assert(!iswhite(gcvalue(&g->l_registry))); 633 assert(!iswhite(gcvalue(&g->l_registry)));
@@ -999,9 +999,8 @@ static int table_query (lua_State *L) {
999 if (i == -1) { 999 if (i == -1) {
1000 lua_pushinteger(L, asize); 1000 lua_pushinteger(L, asize);
1001 lua_pushinteger(L, allocsizenode(t)); 1001 lua_pushinteger(L, allocsizenode(t));
1002 lua_pushinteger(L, isdummy(t) ? 0 : t->lastfree - t->node);
1003 lua_pushinteger(L, t->alimit); 1002 lua_pushinteger(L, t->alimit);
1004 return 4; 1003 return 3;
1005 } 1004 }
1006 else if ((unsigned int)i < asize) { 1005 else if ((unsigned int)i < asize) {
1007 lua_pushinteger(L, i); 1006 lua_pushinteger(L, i);
@@ -1028,6 +1027,16 @@ static int table_query (lua_State *L) {
1028} 1027}
1029 1028
1030 1029
1030static int query_inc (lua_State *L) {
1031 global_State *g = G(L);
1032 lua_pushinteger(L, gettotalobjs(g));
1033 lua_pushinteger(L, g->GCdebt);
1034 lua_pushinteger(L, applygcparam(g, gcpause, 100));
1035 lua_pushinteger(L, applygcparam(g, gcstepmul, 100));
1036 lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize);
1037 return 5;
1038}
1039
1031static int string_query (lua_State *L) { 1040static int string_query (lua_State *L) {
1032 stringtable *tb = &G(L)->strt; 1041 stringtable *tb = &G(L)->strt;
1033 int s = cast_int(luaL_optinteger(L, 1, 0)) - 1; 1042 int s = cast_int(luaL_optinteger(L, 1, 0)) - 1;
@@ -1150,7 +1159,7 @@ static int num2int (lua_State *L) {
1150static int newstate (lua_State *L) { 1159static int newstate (lua_State *L) {
1151 void *ud; 1160 void *ud;
1152 lua_Alloc f = lua_getallocf(L, &ud); 1161 lua_Alloc f = lua_getallocf(L, &ud);
1153 lua_State *L1 = lua_newstate(f, ud); 1162 lua_State *L1 = lua_newstate(f, ud, 0);
1154 if (L1) { 1163 if (L1) {
1155 lua_atpanic(L1, tpanic); 1164 lua_atpanic(L1, tpanic);
1156 lua_pushlightuserdata(L, L1); 1165 lua_pushlightuserdata(L, L1);
@@ -1169,31 +1178,15 @@ static lua_State *getstate (lua_State *L) {
1169 1178
1170 1179
1171static int loadlib (lua_State *L) { 1180static int loadlib (lua_State *L) {
1172 static const luaL_Reg libs[] = {
1173 {LUA_GNAME, luaopen_base},
1174 {"coroutine", luaopen_coroutine},
1175 {"debug", luaopen_debug},
1176 {"io", luaopen_io},
1177 {"os", luaopen_os},
1178 {"math", luaopen_math},
1179 {"string", luaopen_string},
1180 {"table", luaopen_table},
1181 {"T", luaB_opentests},
1182 {NULL, NULL}
1183 };
1184 lua_State *L1 = getstate(L); 1181 lua_State *L1 = getstate(L);
1185 int i; 1182 int what = luaL_checkinteger(L, 2);
1186 luaL_requiref(L1, "package", luaopen_package, 0); 1183 luaL_openselectedlibs(L1, what);
1184 luaL_requiref(L1, "T", luaB_opentests, 0);
1187 lua_assert(lua_type(L1, -1) == LUA_TTABLE); 1185 lua_assert(lua_type(L1, -1) == LUA_TTABLE);
1188 /* 'requiref' should not reload module already loaded... */ 1186 /* 'requiref' should not reload module already loaded... */
1189 luaL_requiref(L1, "package", NULL, 1); /* seg. fault if it reloads */ 1187 luaL_requiref(L1, "T", NULL, 1); /* seg. fault if it reloads */
1190 /* ...but should return the same module */ 1188 /* ...but should return the same module */
1191 lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ)); 1189 lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ));
1192 luaL_getsubtable(L1, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
1193 for (i = 0; libs[i].name; i++) {
1194 lua_pushcfunction(L1, libs[i].func);
1195 lua_setfield(L1, -2, libs[i].name);
1196 }
1197 return 0; 1190 return 0;
1198} 1191}
1199 1192
@@ -1259,7 +1252,7 @@ static int checkpanic (lua_State *L) {
1259 lua_Alloc f = lua_getallocf(L, &ud); 1252 lua_Alloc f = lua_getallocf(L, &ud);
1260 b.paniccode = luaL_optstring(L, 2, ""); 1253 b.paniccode = luaL_optstring(L, 2, "");
1261 b.L = L; 1254 b.L = L;
1262 L1 = lua_newstate(f, ud); /* create new state */ 1255 L1 = lua_newstate(f, ud, 0); /* create new state */
1263 if (L1 == NULL) { /* error? */ 1256 if (L1 == NULL) { /* error? */
1264 lua_pushnil(L); 1257 lua_pushnil(L);
1265 return 1; 1258 return 1;
@@ -1520,8 +1513,11 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
1520 luaL_loadfile(L1, luaL_checkstring(L1, getnum)); 1513 luaL_loadfile(L1, luaL_checkstring(L1, getnum));
1521 } 1514 }
1522 else if EQ("loadstring") { 1515 else if EQ("loadstring") {
1523 const char *s = luaL_checkstring(L1, getnum); 1516 size_t slen;
1524 luaL_loadstring(L1, s); 1517 const char *s = luaL_checklstring(L1, getnum, &slen);
1518 const char *name = getstring;
1519 const char *mode = getstring;
1520 luaL_loadbufferx(L1, s, slen, name, mode);
1525 } 1521 }
1526 else if EQ("newmetatable") { 1522 else if EQ("newmetatable") {
1527 lua_pushboolean(L1, luaL_newmetatable(L1, getstring)); 1523 lua_pushboolean(L1, luaL_newmetatable(L1, getstring));
@@ -1934,6 +1930,7 @@ static const struct luaL_Reg tests_funcs[] = {
1934 {"pushuserdata", pushuserdata}, 1930 {"pushuserdata", pushuserdata},
1935 {"querystr", string_query}, 1931 {"querystr", string_query},
1936 {"querytab", table_query}, 1932 {"querytab", table_query},
1933 {"queryinc", query_inc},
1937 {"ref", tref}, 1934 {"ref", tref},
1938 {"resume", coresume}, 1935 {"resume", coresume},
1939 {"s2d", s2d}, 1936 {"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 07a06081..8e0d2222 100644
--- a/ltm.c
+++ b/ltm.c
@@ -260,7 +260,7 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
260 int nextra = ci->u.l.nextraargs; 260 int nextra = ci->u.l.nextraargs;
261 if (wanted < 0) { 261 if (wanted < 0) {
262 wanted = nextra; /* get all extra arguments available */ 262 wanted = nextra; /* get all extra arguments available */
263 checkstackGCp(L, nextra, where); /* ensure stack space */ 263 checkstackp(L, nextra, where); /* ensure stack space */
264 L->top.p = where + nextra; /* next instruction will need top */ 264 L->top.p = where + nextra; /* next instruction will need top */
265 } 265 }
266 for (i = 0; i < wanted && i < nextra; i++) 266 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 4d71cfff..0a6d6270 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
@@ -376,10 +379,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
376** have different lengths. 379** have different lengths.
377*/ 380*/
378static int l_strcmp (const TString *ts1, const TString *ts2) { 381static int l_strcmp (const TString *ts1, const TString *ts2) {
379 const char *s1 = getstr(ts1); 382 size_t rl1; /* real length */
380 size_t rl1 = tsslen(ts1); /* real length */ 383 const char *s1 = getlstr(ts1, rl1);
381 const char *s2 = getstr(ts2); 384 size_t rl2;
382 size_t rl2 = tsslen(ts2); 385 const char *s2 = getlstr(ts2, rl2);
383 for (;;) { /* for each segment */ 386 for (;;) { /* for each segment */
384 int temp = strcoll(s1, s2); 387 int temp = strcoll(s1, s2);
385 if (temp != 0) /* not equal? */ 388 if (temp != 0) /* not equal? */
@@ -629,8 +632,9 @@ static void copy2buff (StkId top, int n, char *buff) {
629 size_t tl = 0; /* size already copied */ 632 size_t tl = 0; /* size already copied */
630 do { 633 do {
631 TString *st = tsvalue(s2v(top - n)); 634 TString *st = tsvalue(s2v(top - n));
632 size_t l = tsslen(st); /* length of string being copied */ 635 size_t l; /* length of string being copied */
633 memcpy(buff + tl, getstr(st), l * sizeof(char)); 636 const char *s = getlstr(st, l);
637 memcpy(buff + tl, s, l * sizeof(char));
634 tl += l; 638 tl += l;
635 } while (--n > 0); 639 } while (--n > 0);
636} 640}
@@ -1783,15 +1787,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1783 } 1787 }
1784 vmcase(OP_FORLOOP) { 1788 vmcase(OP_FORLOOP) {
1785 StkId ra = RA(i); 1789 StkId ra = RA(i);
1786 if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ 1790 if (ttisinteger(s2v(ra + 1))) { /* integer loop? */
1787 lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); 1791 lua_Unsigned count = l_castS2U(ivalue(s2v(ra)));
1788 if (count > 0) { /* still more iterations? */ 1792 if (count > 0) { /* still more iterations? */
1789 lua_Integer step = ivalue(s2v(ra + 2)); 1793 lua_Integer step = ivalue(s2v(ra + 1));
1790 lua_Integer idx = ivalue(s2v(ra)); /* internal index */ 1794 lua_Integer idx = ivalue(s2v(ra + 2)); /* control variable */
1791 chgivalue(s2v(ra + 1), count - 1); /* update counter */ 1795 chgivalue(s2v(ra), count - 1); /* update counter */
1792 idx = intop(+, idx, step); /* add step to index */ 1796 idx = intop(+, idx, step); /* add step to index */
1793 chgivalue(s2v(ra), idx); /* update internal index */ 1797 chgivalue(s2v(ra + 2), idx); /* update control variable */
1794 setivalue(s2v(ra + 3), idx); /* and control variable */
1795 pc -= GETARG_Bx(i); /* jump back */ 1798 pc -= GETARG_Bx(i); /* jump back */
1796 } 1799 }
1797 } 1800 }
@@ -1808,26 +1811,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1808 vmbreak; 1811 vmbreak;
1809 } 1812 }
1810 vmcase(OP_TFORPREP) { 1813 vmcase(OP_TFORPREP) {
1814 /* before: 'ra' has the iterator function, 'ra + 1' has the state,
1815 'ra + 2' has the initial value for the control variable, and
1816 'ra + 3' has the closing variable. This opcode then swaps the
1817 control and the closing variables and marks the closing variable
1818 as to-be-closed.
1819 */
1811 StkId ra = RA(i); 1820 StkId ra = RA(i);
1812 /* create to-be-closed upvalue (if needed) */ 1821 TValue temp; /* to swap control and closing variables */
1813 halfProtect(luaF_newtbcupval(L, ra + 3)); 1822 setobj(L, &temp, s2v(ra + 3));
1814 pc += GETARG_Bx(i); 1823 setobjs2s(L, ra + 3, ra + 2);
1815 i = *(pc++); /* go to next instruction */ 1824 setobj2s(L, ra + 2, &temp);
1825 /* create to-be-closed upvalue (if closing var. is not nil) */
1826 halfProtect(luaF_newtbcupval(L, ra + 2));
1827 pc += GETARG_Bx(i); /* go to end of the loop */
1828 i = *(pc++); /* fetch next instruction */
1816 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); 1829 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
1817 goto l_tforcall; 1830 goto l_tforcall;
1818 } 1831 }
1819 vmcase(OP_TFORCALL) { 1832 vmcase(OP_TFORCALL) {
1820 l_tforcall: { 1833 l_tforcall: {
1821 StkId ra = RA(i);
1822 /* 'ra' has the iterator function, 'ra + 1' has the state, 1834 /* 'ra' has the iterator function, 'ra + 1' has the state,
1823 'ra + 2' has the control variable, and 'ra + 3' has the 1835 'ra + 2' has the closing variable, and 'ra + 3' has the control
1824 to-be-closed variable. The call will use the stack after 1836 variable. The call will use the stack starting at 'ra + 3',
1825 these values (starting at 'ra + 4') 1837 so that it preserves the first three values, and the first
1838 return will be the new value for the control variable.
1826 */ 1839 */
1827 /* push function, state, and control variable */ 1840 StkId ra = RA(i);
1828 memcpy(ra + 4, ra, 3 * sizeof(*ra)); 1841 setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */
1829 L->top.p = ra + 4 + 3; 1842 setobjs2s(L, ra + 4, ra + 1); /* copy state */
1830 ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ 1843 setobjs2s(L, ra + 3, ra); /* copy function */
1844 L->top.p = ra + 3 + 3;
1845 ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */
1831 updatestack(ci); /* stack may have changed */ 1846 updatestack(ci); /* stack may have changed */
1832 i = *(pc++); /* go to next instruction */ 1847 i = *(pc++); /* go to next instruction */
1833 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); 1848 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
@@ -1836,10 +1851,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1836 vmcase(OP_TFORLOOP) { 1851 vmcase(OP_TFORLOOP) {
1837 l_tforloop: { 1852 l_tforloop: {
1838 StkId ra = RA(i); 1853 StkId ra = RA(i);
1839 if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ 1854 if (!ttisnil(s2v(ra + 3))) /* continue loop? */
1840 setobjs2s(L, ra + 2, ra + 4); /* save control variable */
1841 pc -= GETARG_Bx(i); /* jump back */ 1855 pc -= GETARG_Bx(i); /* jump back */
1842 }
1843 vmbreak; 1856 vmbreak;
1844 }} 1857 }}
1845 vmcase(OP_SETLIST) { 1858 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