aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c105
-rw-r--r--lauxlib.c48
-rw-r--r--lauxlib.h2
-rw-r--r--ldo.c8
-rw-r--r--ldo.h12
-rw-r--r--ldump.c49
-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.h1
-rw-r--r--lparser.c53
-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.c58
-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.c30
-rw-r--r--lundump.h2
-rw-r--r--lvm.c90
-rw-r--r--manual/manual.of162
-rw-r--r--testes/all.lua2
-rw-r--r--testes/api.lua14
-rw-r--r--testes/attrib.lua2
-rw-r--r--testes/calls.lua29
-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
41 files changed, 787 insertions, 791 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/ldo.c b/ldo.c
index bd8d965f..3df6a4b8 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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++)
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..3e91190c 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
@@ -26,6 +28,8 @@ typedef struct {
26 void *data; 28 void *data;
27 int strip; 29 int strip;
28 int status; 30 int status;
31 Table *h; /* table to track saved strings */
32 lua_Integer nstr; /* counter to number saved strings */
29} DumpState; 33} DumpState;
30 34
31 35
@@ -89,14 +93,33 @@ static void dumpInteger (DumpState *D, lua_Integer x) {
89} 93}
90 94
91 95
92static void dumpString (DumpState *D, const TString *s) { 96/*
97** Dump a String. First dump its "size": size==0 means NULL;
98** size==1 is followed by an index and means "reuse saved string with
99** that index"; size>=2 is followed by the string contents with real
100** size==size-2 and means that string, which will be saved with
101** the next available index.
102*/
103static void dumpString (DumpState *D, TString *s) {
93 if (s == NULL) 104 if (s == NULL)
94 dumpSize(D, 0); 105 dumpSize(D, 0);
95 else { 106 else {
96 size_t size = tsslen(s); 107 const TValue *idx = luaH_getstr(D->h, s);
97 const char *str = getstr(s); 108 if (ttisinteger(idx)) { /* string already saved? */
98 dumpSize(D, size + 1); 109 dumpSize(D, 1); /* reuse a saved string */
99 dumpVector(D, str, size); 110 dumpInt(D, ivalue(idx)); /* index of saved string */
111 }
112 else { /* must write and save the string */
113 TValue key, value; /* to save the string in the hash */
114 size_t size = tsslen(s);
115 dumpSize(D, size + 2);
116 dumpVector(D, getstr(s), size);
117 D->nstr++; /* one more saved string */
118 setsvalue(D->L, &key, s); /* the string is the key */
119 setivalue(&value, D->nstr); /* its index is the value */
120 luaH_finishset(D->L, D->h, &key, idx, &value); /* h[s] = nstr */
121 /* integer value does not need barrier */
122 }
100 } 123 }
101} 124}
102 125
@@ -107,7 +130,7 @@ static void dumpCode (DumpState *D, const Proto *f) {
107} 130}
108 131
109 132
110static void dumpFunction(DumpState *D, const Proto *f, TString *psource); 133static void dumpFunction(DumpState *D, const Proto *f);
111 134
112static void dumpConstants (DumpState *D, const Proto *f) { 135static void dumpConstants (DumpState *D, const Proto *f) {
113 int i; 136 int i;
@@ -140,7 +163,7 @@ static void dumpProtos (DumpState *D, const Proto *f) {
140 int n = f->sizep; 163 int n = f->sizep;
141 dumpInt(D, n); 164 dumpInt(D, n);
142 for (i = 0; i < n; i++) 165 for (i = 0; i < n; i++)
143 dumpFunction(D, f->p[i], f->source); 166 dumpFunction(D, f->p[i]);
144} 167}
145 168
146 169
@@ -180,9 +203,9 @@ static void dumpDebug (DumpState *D, const Proto *f) {
180} 203}
181 204
182 205
183static void dumpFunction (DumpState *D, const Proto *f, TString *psource) { 206static void dumpFunction (DumpState *D, const Proto *f) {
184 if (D->strip || f->source == psource) 207 if (D->strip)
185 dumpString(D, NULL); /* no debug info or same source as its parent */ 208 dumpString(D, NULL); /* no debug info */
186 else 209 else
187 dumpString(D, f->source); 210 dumpString(D, f->source);
188 dumpInt(D, f->linedefined); 211 dumpInt(D, f->linedefined);
@@ -215,16 +238,18 @@ static void dumpHeader (DumpState *D) {
215** dump Lua function as precompiled chunk 238** dump Lua function as precompiled chunk
216*/ 239*/
217int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 240int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
218 int strip) { 241 int strip, Table *h) {
219 DumpState D; 242 DumpState D;
220 D.L = L; 243 D.L = L;
221 D.writer = w; 244 D.writer = w;
222 D.data = data; 245 D.data = data;
223 D.strip = strip; 246 D.strip = strip;
224 D.status = 0; 247 D.status = 0;
248 D.h = h;
249 D.nstr = 0;
225 dumpHeader(&D); 250 dumpHeader(&D);
226 dumpByte(&D, f->sizeupvalues); 251 dumpByte(&D, f->sizeupvalues);
227 dumpFunction(&D, f, NULL); 252 dumpFunction(&D, f);
228 return D.status; 253 return D.status;
229} 254}
230 255
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 d0b1e1e5..6d63950c 100644
--- a/lmathlib.c
+++ b/lmathlib.c
@@ -603,28 +603,18 @@ static void setseed (lua_State *L, Rand64 *state,
603} 603}
604 604
605 605
606/*
607** Set a "random" seed. To get some randomness, use the current time
608** and the address of 'L' (in case the machine does address space layout
609** randomization).
610*/
611static void randseed (lua_State *L, RanState *state) {
612 lua_Unsigned seed1 = (lua_Unsigned)time(NULL);
613 lua_Unsigned seed2 = (lua_Unsigned)(size_t)L;
614 setseed(L, state->s, seed1, seed2);
615}
616
617
618static int math_randomseed (lua_State *L) { 606static int math_randomseed (lua_State *L) {
619 RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); 607 RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
608 lua_Unsigned n1, n2;
620 if (lua_isnone(L, 1)) { 609 if (lua_isnone(L, 1)) {
621 randseed(L, state); 610 n1 = luaL_makeseed(L); /* "random" seed */
611 n2 = I2UInt(nextrand(state->s)); /* in case seed is not that random... */
622 } 612 }
623 else { 613 else {
624 lua_Integer n1 = luaL_checkinteger(L, 1); 614 n1 = luaL_checkinteger(L, 1);
625 lua_Integer n2 = luaL_optinteger(L, 2, 0); 615 n2 = luaL_optinteger(L, 2, 0);
626 setseed(L, state->s, n1, n2);
627 } 616 }
617 setseed(L, state->s, n1, n2);
628 return 2; /* return seeds */ 618 return 2; /* return seeds */
629} 619}
630 620
@@ -641,7 +631,7 @@ static const luaL_Reg randfuncs[] = {
641*/ 631*/
642static void setrandfunc (lua_State *L) { 632static void setrandfunc (lua_State *L) {
643 RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0); 633 RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0);
644 randseed(L, state); /* initialize with a "random" seed */ 634 setseed(L, state->s, luaL_makeseed(L), 0); /* initialize with random seed */
645 lua_pop(L, 2); /* remove pushed seeds */ 635 lua_pop(L, 2); /* remove pushed seeds */
646 luaL_setfuncs(L, randfuncs, 1); 636 luaL_setfuncs(L, randfuncs, 1);
647} 637}
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..79dc6b1c 100644
--- a/lobject.h
+++ b/lobject.h
@@ -741,7 +741,6 @@ typedef struct Table {
741 unsigned int alimit; /* "limit" of 'array' array */ 741 unsigned int alimit; /* "limit" of 'array' array */
742 TValue *array; /* array part */ 742 TValue *array; /* array part */
743 Node *node; 743 Node *node;
744 Node *lastfree; /* any free position is before this position */
745 struct Table *metatable; 744 struct Table *metatable;
746 GCObject *gclist; 745 GCObject *gclist;
747} Table; 746} Table;
diff --git a/lparser.c b/lparser.c
index 2b888c7c..81c6df22 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));
@@ -1550,6 +1558,7 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
1550 int prep, endfor; 1558 int prep, endfor;
1551 checknext(ls, TK_DO); 1559 checknext(ls, TK_DO);
1552 prep = luaK_codeABx(fs, forprep[isgen], base, 0); 1560 prep = luaK_codeABx(fs, forprep[isgen], base, 0);
1561 fs->freereg--; /* both 'forprep' remove one register from the stack */
1553 enterblock(fs, &bl, 0); /* scope for declared variables */ 1562 enterblock(fs, &bl, 0); /* scope for declared variables */
1554 adjustlocalvars(ls, nvars); 1563 adjustlocalvars(ls, nvars);
1555 luaK_reserveregs(fs, nvars); 1564 luaK_reserveregs(fs, nvars);
@@ -1572,8 +1581,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1572 int base = fs->freereg; 1581 int base = fs->freereg;
1573 new_localvarliteral(ls, "(for state)"); 1582 new_localvarliteral(ls, "(for state)");
1574 new_localvarliteral(ls, "(for state)"); 1583 new_localvarliteral(ls, "(for state)");
1575 new_localvarliteral(ls, "(for state)"); 1584 new_localvarkind(ls, varname, RDKCONST); /* control variable */
1576 new_localvar(ls, varname);
1577 checknext(ls, '='); 1585 checknext(ls, '=');
1578 exp1(ls); /* initial value */ 1586 exp1(ls); /* initial value */
1579 checknext(ls, ','); 1587 checknext(ls, ',');
@@ -1584,7 +1592,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1584 luaK_int(fs, fs->freereg, 1); 1592 luaK_int(fs, fs->freereg, 1);
1585 luaK_reserveregs(fs, 1); 1593 luaK_reserveregs(fs, 1);
1586 } 1594 }
1587 adjustlocalvars(ls, 3); /* control variables */ 1595 adjustlocalvars(ls, 2); /* start scope for internal variables */
1588 forbody(ls, base, line, 1, 0); 1596 forbody(ls, base, line, 1, 0);
1589} 1597}
1590 1598
@@ -1593,16 +1601,15 @@ static void forlist (LexState *ls, TString *indexname) {
1593 /* forlist -> NAME {,NAME} IN explist forbody */ 1601 /* forlist -> NAME {,NAME} IN explist forbody */
1594 FuncState *fs = ls->fs; 1602 FuncState *fs = ls->fs;
1595 expdesc e; 1603 expdesc e;
1596 int nvars = 5; /* gen, state, control, toclose, 'indexname' */ 1604 int nvars = 4; /* function, state, closing, control */
1597 int line; 1605 int line;
1598 int base = fs->freereg; 1606 int base = fs->freereg;
1599 /* create control variables */ 1607 /* create internal variables */
1600 new_localvarliteral(ls, "(for state)"); 1608 new_localvarliteral(ls, "(for state)"); /* iterator function */
1601 new_localvarliteral(ls, "(for state)"); 1609 new_localvarliteral(ls, "(for state)"); /* state */
1602 new_localvarliteral(ls, "(for state)"); 1610 new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */
1603 new_localvarliteral(ls, "(for state)"); 1611 new_localvarkind(ls, indexname, RDKCONST); /* control variable */
1604 /* create declared variables */ 1612 /* other declared variables */
1605 new_localvar(ls, indexname);
1606 while (testnext(ls, ',')) { 1613 while (testnext(ls, ',')) {
1607 new_localvar(ls, str_checkname(ls)); 1614 new_localvar(ls, str_checkname(ls));
1608 nvars++; 1615 nvars++;
@@ -1610,10 +1617,10 @@ static void forlist (LexState *ls, TString *indexname) {
1610 checknext(ls, TK_IN); 1617 checknext(ls, TK_IN);
1611 line = ls->linenumber; 1618 line = ls->linenumber;
1612 adjust_assign(ls, 4, explist(ls, &e), &e); 1619 adjust_assign(ls, 4, explist(ls, &e), &e);
1613 adjustlocalvars(ls, 4); /* control variables */ 1620 adjustlocalvars(ls, 3); /* start scope for internal variables */
1614 marktobeclosed(fs); /* last control var. must be closed */ 1621 marktobeclosed(fs); /* last internal var. must be closed */
1615 luaK_checkstack(fs, 3); /* extra space to call generator */ 1622 luaK_checkstack(fs, 2); /* extra space to call iterator */
1616 forbody(ls, base, line, nvars - 4, 1); 1623 forbody(ls, base, line, nvars - 3, 1);
1617} 1624}
1618 1625
1619 1626
@@ -1728,14 +1735,14 @@ static void localstat (LexState *ls) {
1728 FuncState *fs = ls->fs; 1735 FuncState *fs = ls->fs;
1729 int toclose = -1; /* index of to-be-closed variable (if any) */ 1736 int toclose = -1; /* index of to-be-closed variable (if any) */
1730 Vardesc *var; /* last variable */ 1737 Vardesc *var; /* last variable */
1731 int vidx, kind; /* index and kind of last variable */ 1738 int vidx; /* index of last variable */
1732 int nvars = 0; 1739 int nvars = 0;
1733 int nexps; 1740 int nexps;
1734 expdesc e; 1741 expdesc e;
1735 do { 1742 do {
1736 vidx = new_localvar(ls, str_checkname(ls)); 1743 TString *vname = str_checkname(ls);
1737 kind = getlocalattribute(ls); 1744 int kind = getlocalattribute(ls);
1738 getlocalvardesc(fs, vidx)->vd.kind = kind; 1745 vidx = new_localvarkind(ls, vname, kind);
1739 if (kind == RDKTOCLOSE) { /* to-be-closed? */ 1746 if (kind == RDKTOCLOSE) { /* to-be-closed? */
1740 if (toclose != -1) /* one already present? */ 1747 if (toclose != -1) /* one already present? */
1741 luaK_semerror(ls, "multiple to-be-closed variables in local list"); 1748 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 3fb575a1..8db26bdc 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..e218778a 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;
@@ -1934,6 +1927,7 @@ static const struct luaL_Reg tests_funcs[] = {
1934 {"pushuserdata", pushuserdata}, 1927 {"pushuserdata", pushuserdata},
1935 {"querystr", string_query}, 1928 {"querystr", string_query},
1936 {"querytab", table_query}, 1929 {"querytab", table_query},
1930 {"queryinc", query_inc},
1937 {"ref", tref}, 1931 {"ref", tref},
1938 {"resume", coresume}, 1932 {"resume", coresume},
1939 {"s2d", s2d}, 1933 {"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 f1852c35..0c93c995 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,8 @@ 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 lua_Integer nstr; /* number of strings in the list */
37} LoadState; 40} LoadState;
38 41
39 42
@@ -110,10 +113,16 @@ static lua_Integer loadInteger (LoadState *S) {
110static TString *loadStringN (LoadState *S, Proto *p) { 113static TString *loadStringN (LoadState *S, Proto *p) {
111 lua_State *L = S->L; 114 lua_State *L = S->L;
112 TString *ts; 115 TString *ts;
116 TValue sv;
113 size_t size = loadSize(S); 117 size_t size = loadSize(S);
114 if (size == 0) /* no string? */ 118 if (size == 0) /* no string? */
115 return NULL; 119 return NULL;
116 else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ 120 else if (size == 1) { /* previously saved string? */
121 int idx = loadInt(S); /* get its index */
122 const TValue *stv = luaH_getint(S->h, idx);
123 return tsvalue(stv);
124 }
125 else if (size -= 2, size <= LUAI_MAXSHORTLEN) { /* short string? */
117 char buff[LUAI_MAXSHORTLEN]; 126 char buff[LUAI_MAXSHORTLEN];
118 loadVector(S, buff, size); /* load string into buffer */ 127 loadVector(S, buff, size); /* load string into buffer */
119 ts = luaS_newlstr(L, buff, size); /* create string */ 128 ts = luaS_newlstr(L, buff, size); /* create string */
@@ -126,6 +135,10 @@ static TString *loadStringN (LoadState *S, Proto *p) {
126 L->top.p--; /* pop string */ 135 L->top.p--; /* pop string */
127 } 136 }
128 luaC_objbarrier(L, p, ts); 137 luaC_objbarrier(L, p, ts);
138 S->nstr++; /* add string to list of saved strings */
139 setsvalue(L, &sv, ts);
140 luaH_setint(L, S->h, S->nstr, &sv);
141 luaC_objbarrierback(L, obj2gco(S->h), ts);
129 return ts; 142 return ts;
130} 143}
131 144
@@ -149,7 +162,7 @@ static void loadCode (LoadState *S, Proto *f) {
149} 162}
150 163
151 164
152static void loadFunction(LoadState *S, Proto *f, TString *psource); 165static void loadFunction(LoadState *S, Proto *f);
153 166
154 167
155static void loadConstants (LoadState *S, Proto *f) { 168static void loadConstants (LoadState *S, Proto *f) {
@@ -198,7 +211,7 @@ static void loadProtos (LoadState *S, Proto *f) {
198 for (i = 0; i < n; i++) { 211 for (i = 0; i < n; i++) {
199 f->p[i] = luaF_newproto(S->L); 212 f->p[i] = luaF_newproto(S->L);
200 luaC_objbarrier(S->L, f, f->p[i]); 213 luaC_objbarrier(S->L, f, f->p[i]);
201 loadFunction(S, f->p[i], f->source); 214 loadFunction(S, f->p[i]);
202 } 215 }
203} 216}
204 217
@@ -255,10 +268,8 @@ static void loadDebug (LoadState *S, Proto *f) {
255} 268}
256 269
257 270
258static void loadFunction (LoadState *S, Proto *f, TString *psource) { 271static void loadFunction (LoadState *S, Proto *f) {
259 f->source = loadStringN(S, f); 272 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); 273 f->linedefined = loadInt(S);
263 f->lastlinedefined = loadInt(S); 274 f->lastlinedefined = loadInt(S);
264 f->numparams = loadByte(S); 275 f->numparams = loadByte(S);
@@ -325,11 +336,16 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
325 cl = luaF_newLclosure(L, loadByte(&S)); 336 cl = luaF_newLclosure(L, loadByte(&S));
326 setclLvalue2s(L, L->top.p, cl); 337 setclLvalue2s(L, L->top.p, cl);
327 luaD_inctop(L); 338 luaD_inctop(L);
339 S.h = luaH_new(L); /* create list of saved strings */
340 S.nstr = 0;
341 sethvalue2s(L, L->top.p, S.h); /* anchor it */
342 luaD_inctop(L);
328 cl->p = luaF_newproto(L); 343 cl->p = luaF_newproto(L);
329 luaC_objbarrier(L, cl, cl->p); 344 luaC_objbarrier(L, cl, cl->p);
330 loadFunction(&S, cl->p, NULL); 345 loadFunction(&S, cl->p);
331 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 346 lua_assert(cl->nupvalues == cl->p->sizeupvalues);
332 luai_verifycode(L, cl->p); 347 luai_verifycode(L, cl->p);
348 L->top.p--; /* pop table */
333 return cl; 349 return cl;
334} 350}
335 351
diff --git a/lundump.h b/lundump.h
index bc71ced8..bfabaa63 100644
--- a/lundump.h
+++ b/lundump.h
@@ -30,6 +30,6 @@ LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
30 30
31/* dump one chunk; from ldump.c */ 31/* dump one chunk; from ldump.c */
32LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 32LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
33 void* data, int strip); 33 void* data, int strip, Table *h);
34 34
35#endif 35#endif
diff --git a/lvm.c b/lvm.c
index 4d71cfff..256d689f 100644
--- a/lvm.c
+++ b/lvm.c
@@ -198,12 +198,15 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
198 198
199/* 199/*
200** Prepare a numerical for loop (opcode OP_FORPREP). 200** Prepare a numerical for loop (opcode OP_FORPREP).
201** Before execution, stack is as follows:
202** ra : initial value
203** ra + 1 : limit
204** ra + 2 : step
201** Return true to skip the loop. Otherwise, 205** Return true to skip the loop. Otherwise,
202** after preparation, stack will be as follows: 206** after preparation, stack will be as follows:
203** ra : internal index (safe copy of the control variable) 207** ra : loop counter (integer loops) or limit (float loops)
204** ra + 1 : loop counter (integer loops) or limit (float loops) 208** ra + 1 : step
205** ra + 2 : step 209** ra + 2 : control variable
206** ra + 3 : control variable
207*/ 210*/
208static int forprep (lua_State *L, StkId ra) { 211static int forprep (lua_State *L, StkId ra) {
209 TValue *pinit = s2v(ra); 212 TValue *pinit = s2v(ra);
@@ -215,7 +218,6 @@ static int forprep (lua_State *L, StkId ra) {
215 lua_Integer limit; 218 lua_Integer limit;
216 if (step == 0) 219 if (step == 0)
217 luaG_runerror(L, "'for' step is zero"); 220 luaG_runerror(L, "'for' step is zero");
218 setivalue(s2v(ra + 3), init); /* control variable */
219 if (forlimit(L, init, plimit, &limit, step)) 221 if (forlimit(L, init, plimit, &limit, step))
220 return 1; /* skip the loop */ 222 return 1; /* skip the loop */
221 else { /* prepare loop counter */ 223 else { /* prepare loop counter */
@@ -230,9 +232,10 @@ static int forprep (lua_State *L, StkId ra) {
230 /* 'step+1' avoids negating 'mininteger' */ 232 /* 'step+1' avoids negating 'mininteger' */
231 count /= l_castS2U(-(step + 1)) + 1u; 233 count /= l_castS2U(-(step + 1)) + 1u;
232 } 234 }
233 /* store the counter in place of the limit (which won't be 235 /* use 'chgivalue' for places that for sure had integers */
234 needed anymore) */ 236 chgivalue(s2v(ra), l_castU2S(count)); /* change init to count */
235 setivalue(plimit, l_castU2S(count)); 237 setivalue(s2v(ra + 1), step); /* change limit to step */
238 chgivalue(s2v(ra + 2), init); /* change step to init */
236 } 239 }
237 } 240 }
238 else { /* try making all values floats */ 241 else { /* try making all values floats */
@@ -249,11 +252,10 @@ static int forprep (lua_State *L, StkId ra) {
249 : luai_numlt(init, limit)) 252 : luai_numlt(init, limit))
250 return 1; /* skip the loop */ 253 return 1; /* skip the loop */
251 else { 254 else {
252 /* make sure internal values are all floats */ 255 /* make sure all values are floats */
253 setfltvalue(plimit, limit); 256 setfltvalue(s2v(ra), limit);
254 setfltvalue(pstep, step); 257 setfltvalue(s2v(ra + 1), step);
255 setfltvalue(s2v(ra), init); /* internal index */ 258 setfltvalue(s2v(ra + 2), init); /* control variable */
256 setfltvalue(s2v(ra + 3), init); /* control variable */
257 } 259 }
258 } 260 }
259 return 0; 261 return 0;
@@ -266,14 +268,13 @@ static int forprep (lua_State *L, StkId ra) {
266** written online with opcode OP_FORLOOP, for performance.) 268** written online with opcode OP_FORLOOP, for performance.)
267*/ 269*/
268static int floatforloop (StkId ra) { 270static int floatforloop (StkId ra) {
269 lua_Number step = fltvalue(s2v(ra + 2)); 271 lua_Number step = fltvalue(s2v(ra + 1));
270 lua_Number limit = fltvalue(s2v(ra + 1)); 272 lua_Number limit = fltvalue(s2v(ra));
271 lua_Number idx = fltvalue(s2v(ra)); /* internal index */ 273 lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */
272 idx = luai_numadd(L, idx, step); /* increment index */ 274 idx = luai_numadd(L, idx, step); /* increment index */
273 if (luai_numlt(0, step) ? luai_numle(idx, limit) 275 if (luai_numlt(0, step) ? luai_numle(idx, limit)
274 : luai_numle(limit, idx)) { 276 : luai_numle(limit, idx)) {
275 chgfltvalue(s2v(ra), idx); /* update internal index */ 277 chgfltvalue(s2v(ra + 2), idx); /* update control variable */
276 setfltvalue(s2v(ra + 3), idx); /* and control variable */
277 return 1; /* jump back */ 278 return 1; /* jump back */
278 } 279 }
279 else 280 else
@@ -1783,15 +1784,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1783 } 1784 }
1784 vmcase(OP_FORLOOP) { 1785 vmcase(OP_FORLOOP) {
1785 StkId ra = RA(i); 1786 StkId ra = RA(i);
1786 if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ 1787 if (ttisinteger(s2v(ra + 1))) { /* integer loop? */
1787 lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); 1788 lua_Unsigned count = l_castS2U(ivalue(s2v(ra)));
1788 if (count > 0) { /* still more iterations? */ 1789 if (count > 0) { /* still more iterations? */
1789 lua_Integer step = ivalue(s2v(ra + 2)); 1790 lua_Integer step = ivalue(s2v(ra + 1));
1790 lua_Integer idx = ivalue(s2v(ra)); /* internal index */ 1791 lua_Integer idx = ivalue(s2v(ra + 2)); /* control variable */
1791 chgivalue(s2v(ra + 1), count - 1); /* update counter */ 1792 chgivalue(s2v(ra), count - 1); /* update counter */
1792 idx = intop(+, idx, step); /* add step to index */ 1793 idx = intop(+, idx, step); /* add step to index */
1793 chgivalue(s2v(ra), idx); /* update internal index */ 1794 chgivalue(s2v(ra + 2), idx); /* update control variable */
1794 setivalue(s2v(ra + 3), idx); /* and control variable */
1795 pc -= GETARG_Bx(i); /* jump back */ 1795 pc -= GETARG_Bx(i); /* jump back */
1796 } 1796 }
1797 } 1797 }
@@ -1808,26 +1808,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1808 vmbreak; 1808 vmbreak;
1809 } 1809 }
1810 vmcase(OP_TFORPREP) { 1810 vmcase(OP_TFORPREP) {
1811 /* before: 'ra' has the iterator function, 'ra + 1' has the state,
1812 'ra + 2' has the initial value for the control variable, and
1813 'ra + 3' has the closing variable. This opcode then swaps the
1814 control and the closing variables and marks the closing variable
1815 as to-be-closed.
1816 */
1811 StkId ra = RA(i); 1817 StkId ra = RA(i);
1812 /* create to-be-closed upvalue (if needed) */ 1818 TValue temp; /* to swap control and closing variables */
1813 halfProtect(luaF_newtbcupval(L, ra + 3)); 1819 setobj(L, &temp, s2v(ra + 3));
1814 pc += GETARG_Bx(i); 1820 setobjs2s(L, ra + 3, ra + 2);
1815 i = *(pc++); /* go to next instruction */ 1821 setobj2s(L, ra + 2, &temp);
1822 /* create to-be-closed upvalue (if closing var. is not nil) */
1823 halfProtect(luaF_newtbcupval(L, ra + 2));
1824 pc += GETARG_Bx(i); /* go to end of the loop */
1825 i = *(pc++); /* fetch next instruction */
1816 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); 1826 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
1817 goto l_tforcall; 1827 goto l_tforcall;
1818 } 1828 }
1819 vmcase(OP_TFORCALL) { 1829 vmcase(OP_TFORCALL) {
1820 l_tforcall: { 1830 l_tforcall: {
1821 StkId ra = RA(i);
1822 /* 'ra' has the iterator function, 'ra + 1' has the state, 1831 /* 'ra' has the iterator function, 'ra + 1' has the state,
1823 'ra + 2' has the control variable, and 'ra + 3' has the 1832 'ra + 2' has the closing variable, and 'ra + 3' has the control
1824 to-be-closed variable. The call will use the stack after 1833 variable. The call will use the stack starting at 'ra + 3',
1825 these values (starting at 'ra + 4') 1834 so that it preserves the first three values, and the first
1835 return will be the new value for the control variable.
1826 */ 1836 */
1827 /* push function, state, and control variable */ 1837 StkId ra = RA(i);
1828 memcpy(ra + 4, ra, 3 * sizeof(*ra)); 1838 setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */
1829 L->top.p = ra + 4 + 3; 1839 setobjs2s(L, ra + 4, ra + 1); /* copy state */
1830 ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ 1840 setobjs2s(L, ra + 3, ra); /* copy function */
1841 L->top.p = ra + 3 + 3;
1842 ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */
1831 updatestack(ci); /* stack may have changed */ 1843 updatestack(ci); /* stack may have changed */
1832 i = *(pc++); /* go to next instruction */ 1844 i = *(pc++); /* go to next instruction */
1833 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); 1845 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
@@ -1836,10 +1848,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1836 vmcase(OP_TFORLOOP) { 1848 vmcase(OP_TFORLOOP) {
1837 l_tforloop: { 1849 l_tforloop: {
1838 StkId ra = RA(i); 1850 StkId ra = RA(i);
1839 if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ 1851 if (!ttisnil(s2v(ra + 3))) /* continue loop? */
1840 setobjs2s(L, ra + 2, ra + 4); /* save control variable */
1841 pc -= GETARG_Bx(i); /* jump back */ 1852 pc -= GETARG_Bx(i); /* jump back */
1842 }
1843 vmbreak; 1853 vmbreak;
1844 }} 1854 }}
1845 vmcase(OP_SETLIST) { 1855 vmcase(OP_SETLIST) {
diff --git a/manual/manual.of b/manual/manual.of
index ad120f5e..c16039b4 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}.
@@ -3671,7 +3665,8 @@ Other upvalues are initialized with @nil.
3671 3665
3672} 3666}
3673 3667
3674@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud);| 3668@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud,
3669 unsigned int seed);|
3675@apii{0,0,-} 3670@apii{0,0,-}
3676 3671
3677Creates a new independent state and returns its main thread. 3672Creates a new independent state and returns its main thread.
@@ -3682,6 +3677,8 @@ Lua will do all memory allocation for this state
3682through this function @seeF{lua_Alloc}. 3677through this function @seeF{lua_Alloc}.
3683The second argument, @id{ud}, is an opaque pointer that Lua 3678The second argument, @id{ud}, is an opaque pointer that Lua
3684passes to the allocator in every call. 3679passes to the allocator in every call.
3680The third argument, @id{seed}, is a seed for the hashing of
3681strings when they are used as table keys.
3685 3682
3686} 3683}
3687 3684
@@ -5737,6 +5734,16 @@ it does not run it.
5737 5734
5738} 5735}
5739 5736
5737@APIEntry{unsigned int luaL_makeseed (lua_State *L);|
5738@apii{0,0,-}
5739
5740Returns a value with a weak attempt for randomness.
5741(It produces that value based on the current date and time
5742and the address of an internal variable,
5743in case the machine has Address Space Layout Randomization.)
5744
5745}
5746
5740 5747
5741@APIEntry{void luaL_newlib (lua_State *L, const luaL_Reg l[]);| 5748@APIEntry{void luaL_newlib (lua_State *L, const luaL_Reg l[]);|
5742@apii{0,1,m} 5749@apii{0,1,m}
@@ -6909,9 +6916,9 @@ including if necessary a path and an extension.
6909(which may depend on the @N{C compiler} and linker used). 6916(which may depend on the @N{C compiler} and linker used).
6910 6917
6911This functionality is not supported by @N{ISO C}. 6918This functionality is not supported by @N{ISO C}.
6912As such, it is only available on some platforms 6919As such, @id{loadlib} is only available on some platforms:
6913(Windows, Linux, Mac OS X, Solaris, BSD, 6920Linux, Windows, Mac OS X, Solaris, BSD,
6914plus other Unix systems that support the @id{dlfcn} standard). 6921plus other Unix systems that support the @id{dlfcn} standard.
6915 6922
6916This function is inherently insecure, 6923This function is inherently insecure,
6917as it allows Lua to call any function in any readable dynamic 6924as it allows Lua to call any function in any readable dynamic
@@ -8109,7 +8116,7 @@ different sequences of results each time the program runs.
8109 8116
8110When called with at least one argument, 8117When called with at least one argument,
8111the integer parameters @id{x} and @id{y} are 8118the integer parameters @id{x} and @id{y} are
8112joined into a 128-bit @emphx{seed} that 8119joined into a @emphx{seed} that
8113is used to reinitialize the pseudo-random generator; 8120is used to reinitialize the pseudo-random generator;
8114equal seeds produce equal sequences of numbers. 8121equal seeds produce equal sequences of numbers.
8115The default for @id{y} is zero. 8122The default for @id{y} is zero.
@@ -9132,7 +9139,7 @@ is a more portable solution.
9132@simplesect{ 9139@simplesect{
9133 9140
9134Here we list the incompatibilities that you may find when moving a program 9141Here we list the incompatibilities that you may find when moving a program
9135from @N{Lua 5.3} to @N{Lua 5.4}. 9142from @N{Lua 5.4} to @N{Lua 5.5}.
9136 9143
9137You can avoid some incompatibilities by compiling Lua with 9144You can avoid some incompatibilities by compiling Lua with
9138appropriate options (see file @id{luaconf.h}). 9145appropriate options (see file @id{luaconf.h}).
@@ -9169,51 +9176,9 @@ change between versions.
9169@itemize{ 9176@itemize{
9170 9177
9171@item{ 9178@item{
9172The coercion of strings to numbers in 9179The control variable in @Rw{for} loops are read only.
9173arithmetic and bitwise operations 9180If you need to change it,
9174has been removed from the core language. 9181declare 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} 9182}
9218 9183
9219} 9184}
@@ -9224,39 +9189,6 @@ like any other error when calling a finalizer.)
9224@itemize{ 9189@itemize{
9225 9190
9226@item{ 9191@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} 9192}
9261 9193
9262} 9194}
@@ -9268,46 +9200,6 @@ to adjust its number of results to one.
9268@itemize{ 9200@itemize{
9269 9201
9270@item{ 9202@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} 9203}
9312 9204
9313} 9205}
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..dece98f5 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -1046,10 +1046,12 @@ assert(a == nil and c == 2) -- 2 == run-time error
1046a, b, c = T.doremote(L1, "return a+") 1046a, b, c = T.doremote(L1, "return a+")
1047assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error 1047assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
1048 1048
1049T.loadlib(L1) 1049T.loadlib(L1, 2) -- load only 'package'
1050a, b, c = T.doremote(L1, [[ 1050a, b, c = T.doremote(L1, [[
1051 string = require'string' 1051 string = require'string'
1052 a = require'_G'; assert(a == _G and require("_G") == a) 1052 local initialG = _G -- not loaded yet
1053 local a = require'_G'; assert(a == _G and require("_G") == a)
1054 assert(initialG == nil and io == nil) -- now we have 'assert'
1053 io = require'io'; assert(type(io.read) == "function") 1055 io = require'io'; assert(type(io.read) == "function")
1054 assert(require("io") == io) 1056 assert(require("io") == io)
1055 a = require'table'; assert(type(a.insert) == "function") 1057 a = require'table'; assert(type(a.insert) == "function")
@@ -1063,7 +1065,7 @@ T.closestate(L1);
1063 1065
1064 1066
1065L1 = T.newstate() 1067L1 = T.newstate()
1066T.loadlib(L1) 1068T.loadlib(L1, 0)
1067T.doremote(L1, "a = {}") 1069T.doremote(L1, "a = {}")
1068T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1; 1070T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
1069 settable -3]]) 1071 settable -3]])
@@ -1446,10 +1448,10 @@ end
1446 1448
1447do -- garbage collection with no extra memory 1449do -- garbage collection with no extra memory
1448 local L = T.newstate() 1450 local L = T.newstate()
1449 T.loadlib(L) 1451 T.loadlib(L, 1 | 2) -- load _G and 'package'
1450 local res = (T.doremote(L, [[ 1452 local res = (T.doremote(L, [[
1451 _ENV = require"_G" 1453 _ENV = _G
1452 local T = require"T" 1454 assert(string == nil)
1453 local a = {} 1455 local a = {}
1454 for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table 1456 for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table
1455 local stsize, stuse = T.querystr() 1457 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 664be1b4..7468d4ab 100644
--- a/testes/calls.lua
+++ b/testes/calls.lua
@@ -346,7 +346,7 @@ if not _port then -- another bug (since 5.2)
346 -- corrupted binary dump: list of upvalue names is larger than number 346 -- corrupted binary dump: list of upvalue names is larger than number
347 -- of upvalues, overflowing the array of upvalues. 347 -- of upvalues, overflowing the array of upvalues.
348 local code = 348 local code =
349 "\x1b\x4c\x75\x61\x54\x00\x19\x93\x0d\x0a\x1a\x0a\x04\x08\x08\x78\x56\z 349 "\x1b\x4c\x75\x61\x55\x00\x19\x93\x0d\x0a\x1a\x0a\x04\x08\x08\x78\x56\z
350 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x77\x40\x00\x86\x40\z 350 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x77\x40\x00\x86\x40\z
351 \x74\x65\x6d\x70\x81\x81\x01\x00\x02\x82\x48\x00\x02\x00\xc7\x00\x01\z 351 \x74\x65\x6d\x70\x81\x81\x01\x00\x02\x82\x48\x00\x02\x00\xc7\x00\x01\z
352 \x00\x80\x80\x80\x82\x00\x00\x80\x81\x82\x78\x80\x82\x81\x86\x40\x74\z 352 \x00\x80\x80\x80\x82\x00\x00\x80\x81\x82\x78\x80\x82\x81\x86\x40\x74\z
@@ -468,7 +468,7 @@ print("testing binary chunks")
468do 468do
469 local header = string.pack("c4BBc6BBB", 469 local header = string.pack("c4BBc6BBB",
470 "\27Lua", -- signature 470 "\27Lua", -- signature
471 0x54, -- version 5.4 (0x54) 471 0x55, -- version 5.5 (0x55)
472 0, -- format 472 0, -- format
473 "\x19\x93\r\n\x1a\n", -- data 473 "\x19\x93\r\n\x1a\n", -- data
474 4, -- size of instruction 474 4, -- size of instruction
@@ -507,5 +507,30 @@ do
507 end 507 end
508end 508end
509 509
510
511do -- check reuse of strings in dumps
512 local str = "|" .. string.rep("X", 50) .. "|"
513 local foo = load(string.format([[
514 local str <const> = "%s"
515 return {
516 function () return str end,
517 function () return str end,
518 function () return str end
519 }
520 ]], str))
521 -- count occurrences of 'str' inside the dump
522 local dump = string.dump(foo)
523 local _, count = string.gsub(dump, str, {})
524 -- there should be only two occurrences:
525 -- one inside the source, other the string itself.
526 assert(count == 2)
527
528 if T then -- check reuse of strings in undump
529 local funcs = load(dump)()
530 assert(string.format("%p", T.listk(funcs[1])[1]) ==
531 string.format("%p", T.listk(funcs[3])[1]))
532 end
533end
534
510print('OK') 535print('OK')
511return deep 536return 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