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 34e64af1..a1eb7dc6 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 dd824e77..f68c5af0 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 markobjectN(g, h->metatable); 536 markobjectN(g, h->metatable);
@@ -556,17 +547,15 @@ static lu_mem traversetable (global_State *g, Table *h) {
556 } 547 }
557 else /* not weak */ 548 else /* not weak */
558 traversestrongtable(g, h); 549 traversestrongtable(g, h);
559 return 1 + h->alimit + 2 * allocsizenode(h);
560} 550}
561 551
562 552
563static int traverseudata (global_State *g, Udata *u) { 553static void traverseudata (global_State *g, Udata *u) {
564 int i; 554 int i;
565 markobjectN(g, u->metatable); /* mark its metatable */ 555 markobjectN(g, u->metatable); /* mark its metatable */
566 for (i = 0; i < u->nuvalue; i++) 556 for (i = 0; i < u->nuvalue; i++)
567 markvalue(g, &u->uv[i].uv); 557 markvalue(g, &u->uv[i].uv);
568 genlink(g, obj2gco(u)); 558 genlink(g, obj2gco(u));
569 return 1 + u->nuvalue;
570} 559}
571 560
572 561
@@ -575,7 +564,7 @@ static int traverseudata (global_State *g, Udata *u) {
575** arrays can be larger than needed; the extra slots are filled with 564** arrays can be larger than needed; the extra slots are filled with
576** NULL, so the use of 'markobjectN') 565** NULL, so the use of 'markobjectN')
577*/ 566*/
578static int traverseproto (global_State *g, Proto *f) { 567static void traverseproto (global_State *g, Proto *f) {
579 int i; 568 int i;
580 markobjectN(g, f->source); 569 markobjectN(g, f->source);
581 for (i = 0; i < f->sizek; i++) /* mark literals */ 570 for (i = 0; i < f->sizek; i++) /* mark literals */
@@ -586,29 +575,26 @@ static int traverseproto (global_State *g, Proto *f) {
586 markobjectN(g, f->p[i]); 575 markobjectN(g, f->p[i]);
587 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ 576 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
588 markobjectN(g, f->locvars[i].varname); 577 markobjectN(g, f->locvars[i].varname);
589 return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
590} 578}
591 579
592 580
593static int traverseCclosure (global_State *g, CClosure *cl) { 581static void traverseCclosure (global_State *g, CClosure *cl) {
594 int i; 582 int i;
595 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ 583 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
596 markvalue(g, &cl->upvalue[i]); 584 markvalue(g, &cl->upvalue[i]);
597 return 1 + cl->nupvalues;
598} 585}
599 586
600/* 587/*
601** Traverse a Lua closure, marking its prototype and its upvalues. 588** Traverse a Lua closure, marking its prototype and its upvalues.
602** (Both can be NULL while closure is being created.) 589** (Both can be NULL while closure is being created.)
603*/ 590*/
604static int traverseLclosure (global_State *g, LClosure *cl) { 591static void traverseLclosure (global_State *g, LClosure *cl) {
605 int i; 592 int i;
606 markobjectN(g, cl->p); /* mark its prototype */ 593 markobjectN(g, cl->p); /* mark its prototype */
607 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ 594 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */
608 UpVal *uv = cl->upvals[i]; 595 UpVal *uv = cl->upvals[i];
609 markobjectN(g, uv); /* mark upvalue */ 596 markobjectN(g, uv); /* mark upvalue */
610 } 597 }
611 return 1 + cl->nupvalues;
612} 598}
613 599
614 600
@@ -624,13 +610,13 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
624** (which can only happen in generational mode) or if the traverse is in 610** (which can only happen in generational mode) or if the traverse is in
625** the propagate phase (which can only happen in incremental mode). 611** the propagate phase (which can only happen in incremental mode).
626*/ 612*/
627static int traversethread (global_State *g, lua_State *th) { 613static void traversethread (global_State *g, lua_State *th) {
628 UpVal *uv; 614 UpVal *uv;
629 StkId o = th->stack.p; 615 StkId o = th->stack.p;
630 if (isold(th) || g->gcstate == GCSpropagate) 616 if (isold(th) || g->gcstate == GCSpropagate)
631 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 617 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
632 if (o == NULL) 618 if (o == NULL)
633 return 1; /* stack not completely built yet */ 619 return; /* stack not completely built yet */
634 lua_assert(g->gcstate == GCSatomic || 620 lua_assert(g->gcstate == GCSatomic ||
635 th->openupval == NULL || isintwups(th)); 621 th->openupval == NULL || isintwups(th));
636 for (; o < th->top.p; o++) /* mark live elements in the stack */ 622 for (; o < th->top.p; o++) /* mark live elements in the stack */
@@ -648,34 +634,35 @@ static int traversethread (global_State *g, lua_State *th) {
648 } 634 }
649 else if (!g->gcemergency) 635 else if (!g->gcemergency)
650 luaD_shrinkstack(th); /* do not change stack in emergency cycle */ 636 luaD_shrinkstack(th); /* do not change stack in emergency cycle */
651 return 1 + stacksize(th);
652} 637}
653 638
654 639
655/* 640/*
656** traverse one gray object, turning it to black. 641** traverse one gray object, turning it to black.
657*/ 642*/
658static lu_mem propagatemark (global_State *g) { 643static void propagatemark (global_State *g) {
659 GCObject *o = g->gray; 644 GCObject *o = g->gray;
660 nw2black(o); 645 nw2black(o);
661 g->gray = *getgclist(o); /* remove from 'gray' list */ 646 g->gray = *getgclist(o); /* remove from 'gray' list */
662 switch (o->tt) { 647 switch (o->tt) {
663 case LUA_VTABLE: return traversetable(g, gco2t(o)); 648 case LUA_VTABLE: traversetable(g, gco2t(o)); break;
664 case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); 649 case LUA_VUSERDATA: traverseudata(g, gco2u(o)); break;
665 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); 650 case LUA_VLCL: traverseLclosure(g, gco2lcl(o)); break;
666 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); 651 case LUA_VCCL: traverseCclosure(g, gco2ccl(o)); break;
667 case LUA_VPROTO: return traverseproto(g, gco2p(o)); 652 case LUA_VPROTO: traverseproto(g, gco2p(o)); break;
668 case LUA_VTHREAD: return traversethread(g, gco2th(o)); 653 case LUA_VTHREAD: traversethread(g, gco2th(o)); break;
669 default: lua_assert(0); return 0; 654 default: lua_assert(0);
670 } 655 }
671} 656}
672 657
673 658
674static lu_mem propagateall (global_State *g) { 659static l_obj propagateall (global_State *g) {
675 lu_mem tot = 0; 660 l_obj work = 0;
676 while (g->gray) 661 while (g->gray) {
677 tot += propagatemark(g); 662 propagatemark(g);
678 return tot; 663 work++;
664 }
665 return work;
679} 666}
680 667
681 668
@@ -684,10 +671,10 @@ static lu_mem propagateall (global_State *g) {
684** Repeat until it converges, that is, nothing new is marked. 'dir' 671** Repeat until it converges, that is, nothing new is marked. 'dir'
685** inverts the direction of the traversals, trying to speed up 672** inverts the direction of the traversals, trying to speed up
686** convergence on chains in the same table. 673** convergence on chains in the same table.
687**
688*/ 674*/
689static void convergeephemerons (global_State *g) { 675static l_obj convergeephemerons (global_State *g) {
690 int changed; 676 int changed;
677 l_obj work = 0;
691 int dir = 0; 678 int dir = 0;
692 do { 679 do {
693 GCObject *w; 680 GCObject *w;
@@ -702,9 +689,11 @@ static void convergeephemerons (global_State *g) {
702 propagateall(g); /* propagate changes */ 689 propagateall(g); /* propagate changes */
703 changed = 1; /* will have to revisit all ephemeron tables */ 690 changed = 1; /* will have to revisit all ephemeron tables */
704 } 691 }
692 work++;
705 } 693 }
706 dir = !dir; /* invert direction next time */ 694 dir = !dir; /* invert direction next time */
707 } while (changed); /* repeat until no more changes */ 695 } while (changed); /* repeat until no more changes */
696 return work;
708} 697}
709 698
710/* }====================================================== */ 699/* }====================================================== */
@@ -720,7 +709,8 @@ static void convergeephemerons (global_State *g) {
720/* 709/*
721** clear entries with unmarked keys from all weaktables in list 'l' 710** clear entries with unmarked keys from all weaktables in list 'l'
722*/ 711*/
723static void clearbykeys (global_State *g, GCObject *l) { 712static l_obj clearbykeys (global_State *g, GCObject *l) {
713 l_obj work = 0;
724 for (; l; l = gco2t(l)->gclist) { 714 for (; l; l = gco2t(l)->gclist) {
725 Table *h = gco2t(l); 715 Table *h = gco2t(l);
726 Node *limit = gnodelast(h); 716 Node *limit = gnodelast(h);
@@ -731,7 +721,9 @@ static void clearbykeys (global_State *g, GCObject *l) {
731 if (isempty(gval(n))) /* is entry empty? */ 721 if (isempty(gval(n))) /* is entry empty? */
732 clearkey(n); /* clear its key */ 722 clearkey(n); /* clear its key */
733 } 723 }
724 work++;
734 } 725 }
726 return work;
735} 727}
736 728
737 729
@@ -739,7 +731,8 @@ static void clearbykeys (global_State *g, GCObject *l) {
739** clear entries with unmarked values from all weaktables in list 'l' up 731** clear entries with unmarked values from all weaktables in list 'l' up
740** to element 'f' 732** to element 'f'
741*/ 733*/
742static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { 734static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
735 l_obj work = 0;
743 for (; l != f; l = gco2t(l)->gclist) { 736 for (; l != f; l = gco2t(l)->gclist) {
744 Table *h = gco2t(l); 737 Table *h = gco2t(l);
745 Node *n, *limit = gnodelast(h); 738 Node *n, *limit = gnodelast(h);
@@ -756,7 +749,9 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
756 if (isempty(gval(n))) /* is entry empty? */ 749 if (isempty(gval(n))) /* is entry empty? */
757 clearkey(n); /* clear its key */ 750 clearkey(n); /* clear its key */
758 } 751 }
752 work++;
759 } 753 }
754 return work;
760} 755}
761 756
762 757
@@ -768,6 +763,7 @@ static void freeupval (lua_State *L, UpVal *uv) {
768 763
769 764
770static void freeobj (lua_State *L, GCObject *o) { 765static void freeobj (lua_State *L, GCObject *o) {
766 G(L)->totalobjs--;
771 switch (o->tt) { 767 switch (o->tt) {
772 case LUA_VPROTO: 768 case LUA_VPROTO:
773 luaF_freeproto(L, gco2p(o)); 769 luaF_freeproto(L, gco2p(o));
@@ -817,10 +813,9 @@ static void freeobj (lua_State *L, GCObject *o) {
817** objects, where a dead object is one marked with the old (non current) 813** objects, where a dead object is one marked with the old (non current)
818** white; change all non-dead objects back to white, preparing for next 814** white; change all non-dead objects back to white, preparing for next
819** collection cycle. Return where to continue the traversal or NULL if 815** collection cycle. Return where to continue the traversal or NULL if
820** list is finished. ('*countout' gets the number of elements traversed.) 816** list is finished.
821*/ 817*/
822static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, 818static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) {
823 int *countout) {
824 global_State *g = G(L); 819 global_State *g = G(L);
825 int ow = otherwhite(g); 820 int ow = otherwhite(g);
826 int i; 821 int i;
@@ -837,8 +832,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
837 p = &curr->next; /* go to next element */ 832 p = &curr->next; /* go to next element */
838 } 833 }
839 } 834 }
840 if (countout)
841 *countout = i; /* number of elements traversed */
842 return (*p == NULL) ? NULL : p; 835 return (*p == NULL) ? NULL : p;
843} 836}
844 837
@@ -849,7 +842,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
849static GCObject **sweeptolive (lua_State *L, GCObject **p) { 842static GCObject **sweeptolive (lua_State *L, GCObject **p) {
850 GCObject **old = p; 843 GCObject **old = p;
851 do { 844 do {
852 p = sweeplist(L, p, 1, NULL); 845 p = sweeplist(L, p, 1);
853 } while (p == old); 846 } while (p == old);
854 return p; 847 return p;
855} 848}
@@ -868,11 +861,8 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) {
868*/ 861*/
869static void checkSizes (lua_State *L, global_State *g) { 862static void checkSizes (lua_State *L, global_State *g) {
870 if (!g->gcemergency) { 863 if (!g->gcemergency) {
871 if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ 864 if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
872 l_mem olddebt = g->GCdebt;
873 luaS_resize(L, g->strt.size / 2); 865 luaS_resize(L, g->strt.size / 2);
874 g->GCestimate += g->GCdebt - olddebt; /* correct estimate */
875 }
876 } 866 }
877} 867}
878 868
@@ -931,18 +921,6 @@ static void GCTM (lua_State *L) {
931 921
932 922
933/* 923/*
934** Call a few finalizers
935*/
936static int runafewfinalizers (lua_State *L, int n) {
937 global_State *g = G(L);
938 int i;
939 for (i = 0; i < n && g->tobefnz; i++)
940 GCTM(L); /* call one finalizer */
941 return i;
942}
943
944
945/*
946** call all pending finalizers 924** call all pending finalizers
947*/ 925*/
948static void callallpendingfinalizers (lua_State *L) { 926static void callallpendingfinalizers (lua_State *L) {
@@ -1050,20 +1028,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
1050 1028
1051/* 1029/*
1052** Set the "time" to wait before starting a new GC cycle; cycle will 1030** Set the "time" to wait before starting a new GC cycle; cycle will
1053** start when memory use hits the threshold of ('estimate' * pause / 1031** start when number of objects in use hits the threshold of
1054** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, 1032** approximately (marked * pause / 100).
1055** because Lua cannot even start with less than PAUSEADJ bytes).
1056*/ 1033*/
1057static void setpause (global_State *g) { 1034static void setpause (global_State *g) {
1058 l_mem threshold, debt; 1035 l_obj threshold = applygcparam(g, gcpause, g->marked);
1059 int pause = getgcparam(g->gcpause); 1036 l_obj debt = threshold - gettotalobjs(g);
1060 l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ 1037 if (debt < 0) debt = 0;
1061 lua_assert(estimate > 0);
1062 threshold = (pause < MAX_LMEM / estimate) /* overflow? */
1063 ? estimate * pause /* no overflow */
1064 : MAX_LMEM; /* overflow; truncate to maximum */
1065 debt = gettotalbytes(g) - threshold;
1066 if (debt > 0) debt = 0;
1067 luaE_setdebt(g, debt); 1038 luaE_setdebt(g, debt);
1068} 1039}
1069 1040
@@ -1303,18 +1274,17 @@ static void atomic2gen (lua_State *L, global_State *g) {
1303 sweep2old(L, &g->tobefnz); 1274 sweep2old(L, &g->tobefnz);
1304 1275
1305 g->gckind = KGC_GEN; 1276 g->gckind = KGC_GEN;
1306 g->lastatomic = 0; 1277 g->GClastmajor = gettotalobjs(g); /* base for memory control */
1307 g->GCestimate = gettotalbytes(g); /* base for memory control */
1308 finishgencycle(L, g); 1278 finishgencycle(L, g);
1309} 1279}
1310 1280
1311 1281
1312/* 1282/*
1313** Set debt for the next minor collection, which will happen when 1283** Set debt for the next minor collection, which will happen when
1314** memory grows 'genminormul'%. 1284** total number of objects grows 'genminormul'%.
1315*/ 1285*/
1316static void setminordebt (global_State *g) { 1286static void setminordebt (global_State *g) {
1317 luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); 1287 luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g)));
1318} 1288}
1319 1289
1320 1290
@@ -1324,14 +1294,12 @@ static void setminordebt (global_State *g) {
1324** are cleared. Then, turn all objects into old and finishes the 1294** are cleared. Then, turn all objects into old and finishes the
1325** collection. 1295** collection.
1326*/ 1296*/
1327static lu_mem entergen (lua_State *L, global_State *g) { 1297static void entergen (lua_State *L, global_State *g) {
1328 lu_mem numobjs;
1329 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ 1298 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */
1330 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1299 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1331 numobjs = atomic(L); /* propagates all and then do the atomic stuff */ 1300 atomic(L); /* propagates all and then do the atomic stuff */
1332 atomic2gen(L, g); 1301 atomic2gen(L, g);
1333 setminordebt(g); /* set debt assuming next cycle will be minor */ 1302 setminordebt(g); /* set debt assuming next cycle will be minor */
1334 return numobjs;
1335} 1303}
1336 1304
1337 1305
@@ -1348,7 +1316,6 @@ static void enterinc (global_State *g) {
1348 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1316 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1349 g->gcstate = GCSpause; 1317 g->gcstate = GCSpause;
1350 g->gckind = KGC_INC; 1318 g->gckind = KGC_INC;
1351 g->lastatomic = 0;
1352} 1319}
1353 1320
1354 1321
@@ -1357,111 +1324,75 @@ static void enterinc (global_State *g) {
1357*/ 1324*/
1358void luaC_changemode (lua_State *L, int newmode) { 1325void luaC_changemode (lua_State *L, int newmode) {
1359 global_State *g = G(L); 1326 global_State *g = G(L);
1360 if (newmode != g->gckind) { 1327 if (newmode != g->gckind) { /* does it need to change? */
1361 if (newmode == KGC_GEN) /* entering generational mode? */ 1328 if (newmode == KGC_INC) { /* entering incremental mode? */
1329 if (g->gckind == KGC_GENMAJOR)
1330 g->gckind = KGC_INC; /* already incremental but in name */
1331 else
1332 enterinc(g); /* entering incremental mode */
1333 }
1334 else {
1335 lua_assert(newmode == KGC_GEN);
1362 entergen(L, g); 1336 entergen(L, g);
1363 else 1337 }
1364 enterinc(g); /* entering incremental mode */
1365 } 1338 }
1366 g->lastatomic = 0;
1367} 1339}
1368 1340
1369 1341
1370/* 1342/*
1371** Does a full collection in generational mode. 1343** Does a full collection in generational mode.
1372*/ 1344*/
1373static lu_mem fullgen (lua_State *L, global_State *g) { 1345static void fullgen (lua_State *L, global_State *g) {
1374 enterinc(g); 1346 enterinc(g);
1375 return entergen(L, g); 1347 entergen(L, g);
1376} 1348}
1377 1349
1378 1350
1379/* 1351/*
1380** Does a major collection after last collection was a "bad collection". 1352** Does a major collector up to the atomic phase and then either
1381** 1353** returns to minor collections or stays doing major ones. If the
1382** When the program is building a big structure, it allocates lots of 1354** number of objects collected this time (numobjs - marked) is more than
1383** memory but generates very little garbage. In those scenarios, 1355** half the number of objects created since the last major collection
1384** the generational mode just wastes time doing small collections, and 1356** (numobjs - lastmajor), it goes back to minor collections.
1385** major collections are frequently what we call a "bad collection", a 1357*/
1386** collection that frees too few objects. To avoid the cost of switching 1358static void genmajorstep (lua_State *L, global_State *g) {
1387** between generational mode and the incremental mode needed for full 1359 l_obj lastmajor = g->GClastmajor; /* count from last collection */
1388** (major) collections, the collector tries to stay in incremental mode 1360 l_obj numobjs = gettotalobjs(g); /* current count */
1389** after a bad collection, and to switch back to generational mode only
1390** after a "good" collection (one that traverses less than 9/8 objects
1391** of the previous one).
1392** The collector must choose whether to stay in incremental mode or to
1393** switch back to generational mode before sweeping. At this point, it
1394** does not know the real memory in use, so it cannot use memory to
1395** decide whether to return to generational mode. Instead, it uses the
1396** number of objects traversed (returned by 'atomic') as a proxy. The
1397** field 'g->lastatomic' keeps this count from the last collection.
1398** ('g->lastatomic != 0' also means that the last collection was bad.)
1399*/
1400static void stepgenfull (lua_State *L, global_State *g) {
1401 lu_mem newatomic; /* count of traversed objects */
1402 lu_mem lastatomic = g->lastatomic; /* count from last collection */
1403 if (g->gckind == KGC_GEN) /* still in generational mode? */
1404 enterinc(g); /* enter incremental mode */
1405 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1361 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1406 newatomic = atomic(L); /* mark everybody */ 1362 atomic(L); /* mark everybody */
1407 if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ 1363 if ((numobjs - g->marked) > ((numobjs - lastmajor) >> 1)) {
1408 atomic2gen(L, g); /* return to generational mode */ 1364 atomic2gen(L, g); /* return to generational mode */
1409 setminordebt(g); 1365 setminordebt(g);
1410 } 1366 }
1411 else { /* another bad collection; stay in incremental mode */ 1367 else { /* bad collection; stay in major mode */
1412 g->GCestimate = gettotalbytes(g); /* first estimate */
1413 entersweep(L); 1368 entersweep(L);
1414 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1369 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1415 setpause(g); 1370 setpause(g);
1416 g->lastatomic = newatomic; 1371 g->GClastmajor = gettotalobjs(g);
1417 } 1372 }
1418} 1373}
1419 1374
1420 1375
1421/* 1376/*
1422** Does a generational "step". 1377** Does a generational "step". If the total number of objects grew
1423** Usually, this means doing a minor collection and setting the debt to 1378** more than 'majormul'% since the last major collection, does a
1424** make another collection when memory grows 'genminormul'% larger. 1379** major collection. Otherwise, does a minor collection.
1425**
1426** However, there are exceptions. If memory grows 'genmajormul'%
1427** larger than it was at the end of the last major collection (kept
1428** in 'g->GCestimate'), the function does a major collection. At the
1429** end, it checks whether the major collection was able to free a
1430** decent amount of memory (at least half the growth in memory since
1431** previous major collection). If so, the collector keeps its state,
1432** and the next collection will probably be minor again. Otherwise,
1433** we have what we call a "bad collection". In that case, set the field
1434** 'g->lastatomic' to signal that fact, so that the next collection will
1435** go to 'stepgenfull'.
1436**
1437** 'GCdebt <= 0' means an explicit call to GC step with "size" zero;
1438** in that case, do a minor collection.
1439*/ 1380*/
1440static void genstep (lua_State *L, global_State *g) { 1381static void genstep (lua_State *L, global_State *g) {
1441 if (g->lastatomic != 0) /* last collection was a bad one? */ 1382 l_obj majorbase = g->GClastmajor; /* count after last major collection */
1442 stepgenfull(L, g); /* do a full step */ 1383 l_obj majorinc = applygcparam(g, genmajormul, majorbase);
1443 else { 1384 if (gettotalobjs(g) > majorbase + majorinc && 0) {
1444 lu_mem majorbase = g->GCestimate; /* memory after last major collection */ 1385 /* do a major collection */
1445 lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); 1386 enterinc(g);
1446 if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { 1387 g->gckind = KGC_GENMAJOR;
1447 lu_mem numobjs = fullgen(L, g); /* do a major collection */ 1388 genmajorstep(L, g);
1448 if (gettotalbytes(g) < majorbase + (majorinc / 2)) { 1389 }
1449 /* collected at least half of memory growth since last major 1390 else { /* regular case; do a minor collection */
1450 collection; keep doing minor collections. */ 1391 g->marked = 0;
1451 lua_assert(g->lastatomic == 0); 1392 youngcollection(L, g);
1452 } 1393 setminordebt(g);
1453 else { /* bad collection */ 1394 lua_assert(g->GClastmajor == majorbase);
1454 g->lastatomic = numobjs; /* signal that last collection was bad */
1455 setpause(g); /* do a long wait for next (major) collection */
1456 }
1457 }
1458 else { /* regular case; do a minor collection */
1459 youngcollection(L, g);
1460 setminordebt(g);
1461 g->GCestimate = majorbase; /* preserve base value */
1462 }
1463 } 1395 }
1464 lua_assert(isdecGCmodegen(g));
1465} 1396}
1466 1397
1467/* }====================================================== */ 1398/* }====================================================== */
@@ -1520,9 +1451,9 @@ void luaC_freeallobjects (lua_State *L) {
1520} 1451}
1521 1452
1522 1453
1523static lu_mem atomic (lua_State *L) { 1454static l_obj atomic (lua_State *L) {
1455 l_obj work = 0;
1524 global_State *g = G(L); 1456 global_State *g = G(L);
1525 lu_mem work = 0;
1526 GCObject *origweak, *origall; 1457 GCObject *origweak, *origall;
1527 GCObject *grayagain = g->grayagain; /* save original list */ 1458 GCObject *grayagain = g->grayagain; /* save original list */
1528 g->grayagain = NULL; 1459 g->grayagain = NULL;
@@ -1539,50 +1470,44 @@ static lu_mem atomic (lua_State *L) {
1539 work += propagateall(g); /* propagate changes */ 1470 work += propagateall(g); /* propagate changes */
1540 g->gray = grayagain; 1471 g->gray = grayagain;
1541 work += propagateall(g); /* traverse 'grayagain' list */ 1472 work += propagateall(g); /* traverse 'grayagain' list */
1542 convergeephemerons(g); 1473 work += convergeephemerons(g);
1543 /* at this point, all strongly accessible objects are marked. */ 1474 /* at this point, all strongly accessible objects are marked. */
1544 /* Clear values from weak tables, before checking finalizers */ 1475 /* Clear values from weak tables, before checking finalizers */
1545 clearbyvalues(g, g->weak, NULL); 1476 work += clearbyvalues(g, g->weak, NULL);
1546 clearbyvalues(g, g->allweak, NULL); 1477 work += clearbyvalues(g, g->allweak, NULL);
1547 origweak = g->weak; origall = g->allweak; 1478 origweak = g->weak; origall = g->allweak;
1548 separatetobefnz(g, 0); /* separate objects to be finalized */ 1479 separatetobefnz(g, 0); /* separate objects to be finalized */
1549 work += markbeingfnz(g); /* mark objects that will be finalized */ 1480 work += markbeingfnz(g); /* mark objects that will be finalized */
1550 work += propagateall(g); /* remark, to propagate 'resurrection' */ 1481 work += propagateall(g); /* remark, to propagate 'resurrection' */
1551 convergeephemerons(g); 1482 work += convergeephemerons(g);
1552 /* at this point, all resurrected objects are marked. */ 1483 /* at this point, all resurrected objects are marked. */
1553 /* remove dead objects from weak tables */ 1484 /* remove dead objects from weak tables */
1554 clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ 1485 work += clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */
1555 clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ 1486 work += clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */
1556 /* clear values from resurrected weak tables */ 1487 /* clear values from resurrected weak tables */
1557 clearbyvalues(g, g->weak, origweak); 1488 work += clearbyvalues(g, g->weak, origweak);
1558 clearbyvalues(g, g->allweak, origall); 1489 work += clearbyvalues(g, g->allweak, origall);
1559 luaS_clearcache(g); 1490 luaS_clearcache(g);
1560 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1491 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
1561 lua_assert(g->gray == NULL); 1492 lua_assert(g->gray == NULL);
1562 return work; /* estimate of slots marked by 'atomic' */ 1493 return work;
1563} 1494}
1564 1495
1565 1496
1566static int sweepstep (lua_State *L, global_State *g, 1497static void sweepstep (lua_State *L, global_State *g,
1567 int nextstate, GCObject **nextlist) { 1498 int nextstate, GCObject **nextlist) {
1568 if (g->sweepgc) { 1499 if (g->sweepgc)
1569 l_mem olddebt = g->GCdebt; 1500 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
1570 int count;
1571 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count);
1572 g->GCestimate += g->GCdebt - olddebt; /* update estimate */
1573 return count;
1574 }
1575 else { /* enter next state */ 1501 else { /* enter next state */
1576 g->gcstate = nextstate; 1502 g->gcstate = nextstate;
1577 g->sweepgc = nextlist; 1503 g->sweepgc = nextlist;
1578 return 0; /* no work done */
1579 } 1504 }
1580} 1505}
1581 1506
1582 1507
1583static lu_mem singlestep (lua_State *L) { 1508static l_obj singlestep (lua_State *L) {
1584 global_State *g = G(L); 1509 global_State *g = G(L);
1585 lu_mem work; 1510 l_obj work;
1586 lua_assert(!g->gcstopem); /* collector is not reentrant */ 1511 lua_assert(!g->gcstopem); /* collector is not reentrant */
1587 g->gcstopem = 1; /* no emergency collections while collecting */ 1512 g->gcstopem = 1; /* no emergency collections while collecting */
1588 switch (g->gcstate) { 1513 switch (g->gcstate) {
@@ -1597,26 +1522,30 @@ static lu_mem singlestep (lua_State *L) {
1597 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1522 g->gcstate = GCSenteratomic; /* finish propagate phase */
1598 work = 0; 1523 work = 0;
1599 } 1524 }
1600 else 1525 else {
1601 work = propagatemark(g); /* traverse one gray object */ 1526 propagatemark(g); /* traverse one gray object */
1527 work = 1;
1528 }
1602 break; 1529 break;
1603 } 1530 }
1604 case GCSenteratomic: { 1531 case GCSenteratomic: {
1605 work = atomic(L); /* work is what was traversed by 'atomic' */ 1532 work = atomic(L);
1606 entersweep(L); 1533 entersweep(L);
1607 g->GCestimate = gettotalbytes(g); /* first estimate */
1608 break; 1534 break;
1609 } 1535 }
1610 case GCSswpallgc: { /* sweep "regular" objects */ 1536 case GCSswpallgc: { /* sweep "regular" objects */
1611 work = sweepstep(L, g, GCSswpfinobj, &g->finobj); 1537 sweepstep(L, g, GCSswpfinobj, &g->finobj);
1538 work = GCSWEEPMAX;
1612 break; 1539 break;
1613 } 1540 }
1614 case GCSswpfinobj: { /* sweep objects with finalizers */ 1541 case GCSswpfinobj: { /* sweep objects with finalizers */
1615 work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1542 sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1543 work = GCSWEEPMAX;
1616 break; 1544 break;
1617 } 1545 }
1618 case GCSswptobefnz: { /* sweep objects to be finalized */ 1546 case GCSswptobefnz: { /* sweep objects to be finalized */
1619 work = sweepstep(L, g, GCSswpend, NULL); 1547 sweepstep(L, g, GCSswpend, NULL);
1548 work = GCSWEEPMAX;
1620 break; 1549 break;
1621 } 1550 }
1622 case GCSswpend: { /* finish sweeps */ 1551 case GCSswpend: { /* finish sweeps */
@@ -1625,10 +1554,11 @@ static lu_mem singlestep (lua_State *L) {
1625 work = 0; 1554 work = 0;
1626 break; 1555 break;
1627 } 1556 }
1628 case GCScallfin: { /* call remaining finalizers */ 1557 case GCScallfin: { /* call finalizers */
1629 if (g->tobefnz && !g->gcemergency) { 1558 if (g->tobefnz && !g->gcemergency) {
1630 g->gcstopem = 0; /* ok collections during finalizers */ 1559 g->gcstopem = 0; /* ok collections during finalizers */
1631 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; 1560 GCTM(L); /* call one finalizer */
1561 work = 1;
1632 } 1562 }
1633 else { /* emergency mode or no more finalizers */ 1563 else { /* emergency mode or no more finalizers */
1634 g->gcstate = GCSpause; /* finish collection */ 1564 g->gcstate = GCSpause; /* finish collection */
@@ -1663,20 +1593,16 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1663** controls when next step will be performed. 1593** controls when next step will be performed.
1664*/ 1594*/
1665static void incstep (lua_State *L, global_State *g) { 1595static void incstep (lua_State *L, global_State *g) {
1666 int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ 1596 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1667 l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; 1597 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1668 l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem))
1669 ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul
1670 : MAX_LMEM; /* overflow; keep maximum value */
1671 do { /* repeat until pause or enough "credit" (negative debt) */ 1598 do { /* repeat until pause or enough "credit" (negative debt) */
1672 lu_mem work = singlestep(L); /* perform one single step */ 1599 l_obj work = singlestep(L); /* perform one single step */
1673 debt -= work; 1600 work2do -= work;
1674 } while (debt > -stepsize && g->gcstate != GCSpause); 1601 } while (work2do > 0 && g->gcstate != GCSpause);
1675 if (g->gcstate == GCSpause) 1602 if (g->gcstate == GCSpause)
1676 setpause(g); /* pause until next cycle */ 1603 setpause(g); /* pause until next cycle */
1677 else { 1604 else {
1678 debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ 1605 luaE_setdebt(g, stepsize);
1679 luaE_setdebt(g, debt);
1680 } 1606 }
1681} 1607}
1682 1608
@@ -1687,13 +1613,21 @@ static void incstep (lua_State *L, global_State *g) {
1687*/ 1613*/
1688void luaC_step (lua_State *L) { 1614void luaC_step (lua_State *L) {
1689 global_State *g = G(L); 1615 global_State *g = G(L);
1616 lua_assert(!g->gcemergency);
1690 if (!gcrunning(g)) /* not running? */ 1617 if (!gcrunning(g)) /* not running? */
1691 luaE_setdebt(g, -2000); 1618 luaE_setdebt(g, 2000);
1692 else { 1619 else {
1693 if(isdecGCmodegen(g)) 1620 switch (g->gckind) {
1694 genstep(L, g); 1621 case KGC_INC:
1695 else 1622 incstep(L, g);
1696 incstep(L, g); 1623 break;
1624 case KGC_GEN:
1625 genstep(L, g);
1626 break;
1627 case KGC_GENMAJOR:
1628 genmajorstep(L, g);
1629 break;
1630 }
1697 } 1631 }
1698} 1632}
1699 1633
@@ -1711,8 +1645,8 @@ static void fullinc (lua_State *L, global_State *g) {
1711 /* finish any pending sweep phase to start a new cycle */ 1645 /* finish any pending sweep phase to start a new cycle */
1712 luaC_runtilstate(L, bitmask(GCSpause)); 1646 luaC_runtilstate(L, bitmask(GCSpause));
1713 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ 1647 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1714 /* estimate must be correct after a full GC cycle */ 1648 /* 'marked' must be correct after a full GC cycle */
1715 lua_assert(g->GCestimate == gettotalbytes(g)); 1649 lua_assert(g->marked == gettotalobjs(g));
1716 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1650 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1717 setpause(g); 1651 setpause(g);
1718} 1652}
@@ -1727,10 +1661,10 @@ void luaC_fullgc (lua_State *L, int isemergency) {
1727 global_State *g = G(L); 1661 global_State *g = G(L);
1728 lua_assert(!g->gcemergency); 1662 lua_assert(!g->gcemergency);
1729 g->gcemergency = isemergency; /* set flag */ 1663 g->gcemergency = isemergency; /* set flag */
1730 if (g->gckind == KGC_INC) 1664 if (g->gckind == KGC_GEN)
1731 fullinc(L, g);
1732 else
1733 fullgen(L, g); 1665 fullgen(L, g);
1666 else
1667 fullinc(L, g);
1734 g->gcemergency = 0; 1668 g->gcemergency = 0;
1735} 1669}
1736 1670
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 556608e4..1c300e86 100644
--- a/lobject.h
+++ b/lobject.h
@@ -743,7 +743,6 @@ typedef struct Table {
743 unsigned int alimit; /* "limit" of 'array' array */ 743 unsigned int alimit; /* "limit" of 'array' array */
744 TValue *array; /* array part */ 744 TValue *array; /* array part */
745 Node *node; 745 Node *node;
746 Node *lastfree; /* any free position is before this position */
747 struct Table *metatable; 746 struct Table *metatable;
748 GCObject *gclist; 747 GCObject *gclist;
749} Table; 748} Table;
diff --git a/lparser.c b/lparser.c
index b745f236..2ac04160 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 06667dac..37301c3c 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 40ff89aa..488d2c5a 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 02aed64f..1df15e53 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 f3748a99..7def905b 100644
--- a/lundump.h
+++ b/lundump.h
@@ -31,6 +31,6 @@ LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
31 31
32/* dump one chunk; from ldump.c */ 32/* dump one chunk; from ldump.c */
33LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 33LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
34 void* data, int strip); 34 void* data, int strip, Table *h);
35 35
36#endif 36#endif
diff --git a/lvm.c b/lvm.c
index 2b437bdf..a3128c3d 100644
--- a/lvm.c
+++ b/lvm.c
@@ -196,12 +196,15 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
196 196
197/* 197/*
198** Prepare a numerical for loop (opcode OP_FORPREP). 198** Prepare a numerical for loop (opcode OP_FORPREP).
199** Before execution, stack is as follows:
200** ra : initial value
201** ra + 1 : limit
202** ra + 2 : step
199** Return true to skip the loop. Otherwise, 203** Return true to skip the loop. Otherwise,
200** after preparation, stack will be as follows: 204** after preparation, stack will be as follows:
201** ra : internal index (safe copy of the control variable) 205** ra : loop counter (integer loops) or limit (float loops)
202** ra + 1 : loop counter (integer loops) or limit (float loops) 206** ra + 1 : step
203** ra + 2 : step 207** ra + 2 : control variable
204** ra + 3 : control variable
205*/ 208*/
206static int forprep (lua_State *L, StkId ra) { 209static int forprep (lua_State *L, StkId ra) {
207 TValue *pinit = s2v(ra); 210 TValue *pinit = s2v(ra);
@@ -213,7 +216,6 @@ static int forprep (lua_State *L, StkId ra) {
213 lua_Integer limit; 216 lua_Integer limit;
214 if (step == 0) 217 if (step == 0)
215 luaG_runerror(L, "'for' step is zero"); 218 luaG_runerror(L, "'for' step is zero");
216 setivalue(s2v(ra + 3), init); /* control variable */
217 if (forlimit(L, init, plimit, &limit, step)) 219 if (forlimit(L, init, plimit, &limit, step))
218 return 1; /* skip the loop */ 220 return 1; /* skip the loop */
219 else { /* prepare loop counter */ 221 else { /* prepare loop counter */
@@ -228,9 +230,10 @@ static int forprep (lua_State *L, StkId ra) {
228 /* 'step+1' avoids negating 'mininteger' */ 230 /* 'step+1' avoids negating 'mininteger' */
229 count /= l_castS2U(-(step + 1)) + 1u; 231 count /= l_castS2U(-(step + 1)) + 1u;
230 } 232 }
231 /* store the counter in place of the limit (which won't be 233 /* use 'chgivalue' for places that for sure had integers */
232 needed anymore) */ 234 chgivalue(s2v(ra), l_castU2S(count)); /* change init to count */
233 setivalue(plimit, l_castU2S(count)); 235 setivalue(s2v(ra + 1), step); /* change limit to step */
236 chgivalue(s2v(ra + 2), init); /* change step to init */
234 } 237 }
235 } 238 }
236 else { /* try making all values floats */ 239 else { /* try making all values floats */
@@ -247,11 +250,10 @@ static int forprep (lua_State *L, StkId ra) {
247 : luai_numlt(init, limit)) 250 : luai_numlt(init, limit))
248 return 1; /* skip the loop */ 251 return 1; /* skip the loop */
249 else { 252 else {
250 /* make sure internal values are all floats */ 253 /* make sure all values are floats */
251 setfltvalue(plimit, limit); 254 setfltvalue(s2v(ra), limit);
252 setfltvalue(pstep, step); 255 setfltvalue(s2v(ra + 1), step);
253 setfltvalue(s2v(ra), init); /* internal index */ 256 setfltvalue(s2v(ra + 2), init); /* control variable */
254 setfltvalue(s2v(ra + 3), init); /* control variable */
255 } 257 }
256 } 258 }
257 return 0; 259 return 0;
@@ -264,14 +266,13 @@ static int forprep (lua_State *L, StkId ra) {
264** written online with opcode OP_FORLOOP, for performance.) 266** written online with opcode OP_FORLOOP, for performance.)
265*/ 267*/
266static int floatforloop (StkId ra) { 268static int floatforloop (StkId ra) {
267 lua_Number step = fltvalue(s2v(ra + 2)); 269 lua_Number step = fltvalue(s2v(ra + 1));
268 lua_Number limit = fltvalue(s2v(ra + 1)); 270 lua_Number limit = fltvalue(s2v(ra));
269 lua_Number idx = fltvalue(s2v(ra)); /* internal index */ 271 lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */
270 idx = luai_numadd(L, idx, step); /* increment index */ 272 idx = luai_numadd(L, idx, step); /* increment index */
271 if (luai_numlt(0, step) ? luai_numle(idx, limit) 273 if (luai_numlt(0, step) ? luai_numle(idx, limit)
272 : luai_numle(limit, idx)) { 274 : luai_numle(limit, idx)) {
273 chgfltvalue(s2v(ra), idx); /* update internal index */ 275 chgfltvalue(s2v(ra + 2), idx); /* update control variable */
274 setfltvalue(s2v(ra + 3), idx); /* and control variable */
275 return 1; /* jump back */ 276 return 1; /* jump back */
276 } 277 }
277 else 278 else
@@ -1787,15 +1788,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1787 } 1788 }
1788 vmcase(OP_FORLOOP) { 1789 vmcase(OP_FORLOOP) {
1789 StkId ra = RA(i); 1790 StkId ra = RA(i);
1790 if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ 1791 if (ttisinteger(s2v(ra + 1))) { /* integer loop? */
1791 lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); 1792 lua_Unsigned count = l_castS2U(ivalue(s2v(ra)));
1792 if (count > 0) { /* still more iterations? */ 1793 if (count > 0) { /* still more iterations? */
1793 lua_Integer step = ivalue(s2v(ra + 2)); 1794 lua_Integer step = ivalue(s2v(ra + 1));
1794 lua_Integer idx = ivalue(s2v(ra)); /* internal index */ 1795 lua_Integer idx = ivalue(s2v(ra + 2)); /* control variable */
1795 chgivalue(s2v(ra + 1), count - 1); /* update counter */ 1796 chgivalue(s2v(ra), count - 1); /* update counter */
1796 idx = intop(+, idx, step); /* add step to index */ 1797 idx = intop(+, idx, step); /* add step to index */
1797 chgivalue(s2v(ra), idx); /* update internal index */ 1798 chgivalue(s2v(ra + 2), idx); /* update control variable */
1798 setivalue(s2v(ra + 3), idx); /* and control variable */
1799 pc -= GETARG_Bx(i); /* jump back */ 1799 pc -= GETARG_Bx(i); /* jump back */
1800 } 1800 }
1801 } 1801 }
@@ -1812,26 +1812,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1812 vmbreak; 1812 vmbreak;
1813 } 1813 }
1814 vmcase(OP_TFORPREP) { 1814 vmcase(OP_TFORPREP) {
1815 /* before: 'ra' has the iterator function, 'ra + 1' has the state,
1816 'ra + 2' has the initial value for the control variable, and
1817 'ra + 3' has the closing variable. This opcode then swaps the
1818 control and the closing variables and marks the closing variable
1819 as to-be-closed.
1820 */
1815 StkId ra = RA(i); 1821 StkId ra = RA(i);
1816 /* create to-be-closed upvalue (if needed) */ 1822 TValue temp; /* to swap control and closing variables */
1817 halfProtect(luaF_newtbcupval(L, ra + 3)); 1823 setobj(L, &temp, s2v(ra + 3));
1818 pc += GETARG_Bx(i); 1824 setobjs2s(L, ra + 3, ra + 2);
1819 i = *(pc++); /* go to next instruction */ 1825 setobj2s(L, ra + 2, &temp);
1826 /* create to-be-closed upvalue (if closing var. is not nil) */
1827 halfProtect(luaF_newtbcupval(L, ra + 2));
1828 pc += GETARG_Bx(i); /* go to end of the loop */
1829 i = *(pc++); /* fetch next instruction */
1820 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); 1830 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
1821 goto l_tforcall; 1831 goto l_tforcall;
1822 } 1832 }
1823 vmcase(OP_TFORCALL) { 1833 vmcase(OP_TFORCALL) {
1824 l_tforcall: { 1834 l_tforcall: {
1825 StkId ra = RA(i);
1826 /* 'ra' has the iterator function, 'ra + 1' has the state, 1835 /* 'ra' has the iterator function, 'ra + 1' has the state,
1827 'ra + 2' has the control variable, and 'ra + 3' has the 1836 'ra + 2' has the closing variable, and 'ra + 3' has the control
1828 to-be-closed variable. The call will use the stack after 1837 variable. The call will use the stack starting at 'ra + 3',
1829 these values (starting at 'ra + 4') 1838 so that it preserves the first three values, and the first
1839 return will be the new value for the control variable.
1830 */ 1840 */
1831 /* push function, state, and control variable */ 1841 StkId ra = RA(i);
1832 memcpy(ra + 4, ra, 3 * sizeof(*ra)); 1842 setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */
1833 L->top.p = ra + 4 + 3; 1843 setobjs2s(L, ra + 4, ra + 1); /* copy state */
1834 ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ 1844 setobjs2s(L, ra + 3, ra); /* copy function */
1845 L->top.p = ra + 3 + 3;
1846 ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */
1835 updatestack(ci); /* stack may have changed */ 1847 updatestack(ci); /* stack may have changed */
1836 i = *(pc++); /* go to next instruction */ 1848 i = *(pc++); /* go to next instruction */
1837 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); 1849 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
@@ -1840,10 +1852,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1840 vmcase(OP_TFORLOOP) { 1852 vmcase(OP_TFORLOOP) {
1841 l_tforloop: { 1853 l_tforloop: {
1842 StkId ra = RA(i); 1854 StkId ra = RA(i);
1843 if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ 1855 if (!ttisnil(s2v(ra + 3))) /* continue loop? */
1844 setobjs2s(L, ra + 2, ra + 4); /* save control variable */
1845 pc -= GETARG_Bx(i); /* jump back */ 1856 pc -= GETARG_Bx(i); /* jump back */
1846 }
1847 vmbreak; 1857 vmbreak;
1848 }} 1858 }}
1849 vmcase(OP_SETLIST) { 1859 vmcase(OP_SETLIST) {
diff --git a/manual/manual.of b/manual/manual.of
index f8d8ddd4..1e219f9a 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.
@@ -9128,7 +9135,7 @@ is a more portable solution.
9128@simplesect{ 9135@simplesect{
9129 9136
9130Here we list the incompatibilities that you may find when moving a program 9137Here we list the incompatibilities that you may find when moving a program
9131from @N{Lua 5.3} to @N{Lua 5.4}. 9138from @N{Lua 5.4} to @N{Lua 5.5}.
9132 9139
9133You can avoid some incompatibilities by compiling Lua with 9140You can avoid some incompatibilities by compiling Lua with
9134appropriate options (see file @id{luaconf.h}). 9141appropriate options (see file @id{luaconf.h}).
@@ -9165,51 +9172,9 @@ change between versions.
9165@itemize{ 9172@itemize{
9166 9173
9167@item{ 9174@item{
9168The coercion of strings to numbers in 9175The control variable in @Rw{for} loops are read only.
9169arithmetic and bitwise operations 9176If you need to change it,
9170has been removed from the core language. 9177declare a local variable with the same name in the loop body.
9171The string library does a similar job
9172for arithmetic (but not for bitwise) operations
9173using the string metamethods.
9174However, unlike in previous versions,
9175the new implementation preserves the implicit type of the numeral
9176in the string.
9177For instance, the result of @T{"1" + "2"} now is an integer,
9178not a float.
9179}
9180
9181@item{
9182Literal decimal integer constants that overflow are read as floats,
9183instead of wrapping around.
9184You can use hexadecimal notation for such constants if you
9185want the old behavior
9186(reading them as integers with wrap around).
9187}
9188
9189@item{
9190The use of the @idx{__lt} metamethod to emulate @idx{__le}
9191has been removed.
9192When needed, this metamethod must be explicitly defined.
9193}
9194
9195@item{
9196The semantics of the numerical @Rw{for} loop
9197over integers changed in some details.
9198In particular, the control variable never wraps around.
9199}
9200
9201@item{
9202A label for a @Rw{goto} cannot be declared where a label with the same
9203name is visible, even if this other label is declared in an enclosing
9204block.
9205}
9206
9207@item{
9208When finalizing an object,
9209Lua does not ignore @idx{__gc} metamethods that are not functions.
9210Any value will be called, if present.
9211(Non-callable values will generate a warning,
9212like any other error when calling a finalizer.)
9213} 9178}
9214 9179
9215} 9180}
@@ -9220,39 +9185,6 @@ like any other error when calling a finalizer.)
9220@itemize{ 9185@itemize{
9221 9186
9222@item{ 9187@item{
9223The function @Lid{print} does not call @Lid{tostring}
9224to format its arguments;
9225instead, it has this functionality hardwired.
9226You should use @idx{__tostring} to modify how values are printed.
9227}
9228
9229@item{
9230The pseudo-random number generator used by the function @Lid{math.random}
9231now starts with a somewhat random seed.
9232Moreover, it uses a different algorithm.
9233}
9234
9235@item{
9236By default, the decoding functions in the @Lid{utf8} library
9237do not accept surrogates as valid code points.
9238An extra parameter in these functions makes them more permissive.
9239}
9240
9241@item{
9242The options @St{setpause} and @St{setstepmul}
9243of the function @Lid{collectgarbage} are deprecated.
9244You should use the new option @St{incremental} to set them.
9245}
9246
9247@item{
9248The function @Lid{io.lines} now returns four values,
9249instead of just one.
9250That can be a problem when it is used as the sole
9251argument to another function that has optional parameters,
9252such as in @T{load(io.lines(filename, "L"))}.
9253To fix that issue,
9254you can wrap the call into parentheses,
9255to adjust its number of results to one.
9256} 9188}
9257 9189
9258} 9190}
@@ -9264,46 +9196,6 @@ to adjust its number of results to one.
9264@itemize{ 9196@itemize{
9265 9197
9266@item{ 9198@item{
9267Full userdata now has an arbitrary number of associated user values.
9268Therefore, the functions @id{lua_newuserdata},
9269@id{lua_setuservalue}, and @id{lua_getuservalue} were
9270replaced by @Lid{lua_newuserdatauv},
9271@Lid{lua_setiuservalue}, and @Lid{lua_getiuservalue},
9272which have an extra argument.
9273
9274For compatibility, the old names still work as macros assuming
9275one single user value.
9276Note, however, that userdata with zero user values
9277are more efficient memory-wise.
9278}
9279
9280@item{
9281The function @Lid{lua_resume} has an extra parameter.
9282This out parameter returns the number of values on
9283the top of the stack that were yielded or returned by the coroutine.
9284(In previous versions,
9285those values were the entire stack.)
9286}
9287
9288@item{
9289The function @Lid{lua_version} returns the version number,
9290instead of an address of the version number.
9291The Lua core should work correctly with libraries using their
9292own static copies of the same core,
9293so there is no need to check whether they are using the same
9294address space.
9295}
9296
9297@item{
9298The constant @id{LUA_ERRGCMM} was removed.
9299Errors in finalizers are never propagated;
9300instead, they generate a warning.
9301}
9302
9303@item{
9304The options @idx{LUA_GCSETPAUSE} and @idx{LUA_GCSETSTEPMUL}
9305of the function @Lid{lua_gc} are deprecated.
9306You should use the new option @id{LUA_GCINC} to set them.
9307} 9199}
9308 9200
9309} 9201}
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 2d562a24..559ca935 100644
--- a/testes/calls.lua
+++ b/testes/calls.lua
@@ -346,7 +346,7 @@ do -- 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 be00bf3f..149e9c76 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