aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c76
-rw-r--r--ldo.c8
-rw-r--r--ldo.h12
-rw-r--r--lgc.c417
-rw-r--r--lgc.h58
-rw-r--r--linit.c51
-rw-r--r--llimits.h21
-rw-r--r--lmem.c8
-rw-r--r--lmem.h2
-rw-r--r--lobject.h1
-rw-r--r--lstate.c28
-rw-r--r--lstate.h21
-rw-r--r--ltable.c80
-rw-r--r--ltable.h14
-rw-r--r--ltests.c54
-rw-r--r--ltests.h4
-rw-r--r--ltm.c2
-rw-r--r--ltm.h4
-rw-r--r--lua.c6
-rw-r--r--lualib.h39
-rw-r--r--testes/api.lua14
-rw-r--r--testes/coroutine.lua2
-rw-r--r--testes/nextvar.lua4
23 files changed, 475 insertions, 451 deletions
diff --git a/lapi.c b/lapi.c
index 34e64af1..b2ac0c57 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1145,7 +1145,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1145 } 1145 }
1146 case LUA_GCRESTART: { 1146 case LUA_GCRESTART: {
1147 luaE_setdebt(g, 0); 1147 luaE_setdebt(g, 0);
1148 g->gcstp = 0; /* (GCSTPGC must be already zero here) */ 1148 g->gcstp = 0; /* (bit GCSTPGC must be zero here) */
1149 break; 1149 break;
1150 } 1150 }
1151 case LUA_GCCOLLECT: { 1151 case LUA_GCCOLLECT: {
@@ -1154,42 +1154,46 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1154 } 1154 }
1155 case LUA_GCCOUNT: { 1155 case LUA_GCCOUNT: {
1156 /* GC values are expressed in Kbytes: #bytes/2^10 */ 1156 /* GC values are expressed in Kbytes: #bytes/2^10 */
1157 res = cast_int(gettotalbytes(g) >> 10); 1157 res = cast_int(g->totalbytes >> 10);
1158 break; 1158 break;
1159 } 1159 }
1160 case LUA_GCCOUNTB: { 1160 case LUA_GCCOUNTB: {
1161 res = cast_int(gettotalbytes(g) & 0x3ff); 1161 res = cast_int(g->totalbytes & 0x3ff);
1162 break; 1162 break;
1163 } 1163 }
1164 case LUA_GCSTEP: { 1164 case LUA_GCSTEP: {
1165 int data = va_arg(argp, int); 1165 int todo = va_arg(argp, int); /* work to be done */
1166 l_mem debt = 1; /* =1 to signal that it did an actual step */ 1166 int didsomething = 0;
1167 lu_byte oldstp = g->gcstp; 1167 lu_byte oldstp = g->gcstp;
1168 g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */ 1168 g->gcstp = 0; /* allow GC to run (bit GCSTPGC must be zero here) */
1169 if (data == 0) { 1169 if (todo == 0)
1170 luaE_setdebt(g, 0); /* do a basic step */ 1170 todo = 1 << g->gcstepsize; /* standard step size */
1171 luaC_step(L); 1171 while (todo >= g->GCdebt) { /* enough to run a step? */
1172 } 1172 todo -= g->GCdebt; /* decrement 'todo' */
1173 else { /* add 'data' to total debt */ 1173 luaC_step(L); /* run one basic step */
1174 debt = cast(l_mem, data) * 1024 + g->GCdebt; 1174 didsomething = 1;
1175 luaE_setdebt(g, debt); 1175 if (g->gckind == KGC_GEN) /* minor collections? */
1176 luaC_checkGC(L); 1176 todo = 0; /* doesn't make sense to repeat in this case */
1177 else if (g->gcstate == GCSpause)
1178 break; /* don't run more than one cycle */
1177 } 1179 }
1180 /* remove remaining 'todo' from total debt */
1181 luaE_setdebt(g, g->GCdebt - todo);
1178 g->gcstp = oldstp; /* restore previous state */ 1182 g->gcstp = oldstp; /* restore previous state */
1179 if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ 1183 if (didsomething && g->gcstate == GCSpause) /* end of cycle? */
1180 res = 1; /* signal it */ 1184 res = 1; /* signal it */
1181 break; 1185 break;
1182 } 1186 }
1183 case LUA_GCSETPAUSE: { 1187 case LUA_GCSETPAUSE: {
1184 int data = va_arg(argp, int); 1188 unsigned int data = va_arg(argp, unsigned int);
1185 res = getgcparam(g->gcpause); 1189 res = applygcparam(g, gcpause, 100);
1186 setgcparam(g->gcpause, data); 1190 setgcparam(g, gcpause, data);
1187 break; 1191 break;
1188 } 1192 }
1189 case LUA_GCSETSTEPMUL: { 1193 case LUA_GCSETSTEPMUL: {
1190 int data = va_arg(argp, int); 1194 unsigned int data = va_arg(argp, unsigned int);
1191 res = getgcparam(g->gcstepmul); 1195 res = applygcparam(g, gcstepmul, 100);
1192 setgcparam(g->gcstepmul, data); 1196 setgcparam(g, gcstepmul, data);
1193 break; 1197 break;
1194 } 1198 }
1195 case LUA_GCISRUNNING: { 1199 case LUA_GCISRUNNING: {
@@ -1197,27 +1201,28 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1197 break; 1201 break;
1198 } 1202 }
1199 case LUA_GCGEN: { 1203 case LUA_GCGEN: {
1200 int minormul = va_arg(argp, int); 1204 unsigned int minormul = va_arg(argp, unsigned int);
1201 int majormul = va_arg(argp, int); 1205 unsigned int majormul = va_arg(argp, unsigned int);
1202 res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1206 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1203 if (minormul != 0) 1207 if (minormul != 0)
1204 g->genminormul = minormul; 1208 setgcparam(g, genminormul, minormul);
1205 if (majormul != 0) 1209 if (majormul != 0)
1206 setgcparam(g->genmajormul, majormul); 1210 setgcparam(g, genmajormul, majormul);
1207 luaC_changemode(L, KGC_GEN); 1211 luaC_changemode(L, KGC_GEN);
1208 break; 1212 break;
1209 } 1213 }
1210 case LUA_GCINC: { 1214 case LUA_GCINC: {
1211 int pause = va_arg(argp, int); 1215 unsigned int pause = va_arg(argp, unsigned int);
1212 int stepmul = va_arg(argp, int); 1216 unsigned int stepmul = va_arg(argp, unsigned int);
1213 int stepsize = va_arg(argp, int); 1217 unsigned int stepsize = va_arg(argp, unsigned int);
1214 res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1218 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1215 if (pause != 0) 1219 if (pause != 0)
1216 setgcparam(g->gcpause, pause); 1220 setgcparam(g, gcpause, pause);
1217 if (stepmul != 0) 1221 if (stepmul != 0)
1218 setgcparam(g->gcstepmul, stepmul); 1222 setgcparam(g, gcstepmul, stepmul);
1219 if (stepsize != 0) 1223 if (stepsize != 0)
1220 g->gcstepsize = stepsize; 1224 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
1225 : log2maxs(l_obj);
1221 luaC_changemode(L, KGC_INC); 1226 luaC_changemode(L, KGC_INC);
1222 break; 1227 break;
1223 } 1228 }
@@ -1285,13 +1290,14 @@ LUA_API void lua_toclose (lua_State *L, int idx) {
1285LUA_API void lua_concat (lua_State *L, int n) { 1290LUA_API void lua_concat (lua_State *L, int n) {
1286 lua_lock(L); 1291 lua_lock(L);
1287 api_checknelems(L, n); 1292 api_checknelems(L, n);
1288 if (n > 0) 1293 if (n > 0) {
1289 luaV_concat(L, n); 1294 luaV_concat(L, n);
1295 luaC_checkGC(L);
1296 }
1290 else { /* nothing to concatenate */ 1297 else { /* nothing to concatenate */
1291 setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ 1298 setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */
1292 api_incr_top(L); 1299 api_incr_top(L);
1293 } 1300 }
1294 luaC_checkGC(L);
1295 lua_unlock(L); 1301 lua_unlock(L);
1296} 1302}
1297 1303
diff --git a/ldo.c b/ldo.c
index c30cde76..54518aff 100644
--- a/ldo.c
+++ b/ldo.c
@@ -416,7 +416,7 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
416StkId luaD_tryfuncTM (lua_State *L, StkId func) { 416StkId luaD_tryfuncTM (lua_State *L, StkId func) {
417 const TValue *tm; 417 const TValue *tm;
418 StkId p; 418 StkId p;
419 checkstackGCp(L, 1, func); /* space for metamethod */ 419 checkstackp(L, 1, func); /* space for metamethod */
420 tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ 420 tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */
421 if (l_unlikely(ttisnil(tm))) 421 if (l_unlikely(ttisnil(tm)))
422 luaG_callerror(L, s2v(func)); /* nothing to call */ 422 luaG_callerror(L, s2v(func)); /* nothing to call */
@@ -521,7 +521,7 @@ l_sinline int precallC (lua_State *L, StkId func, int nresults,
521 lua_CFunction f) { 521 lua_CFunction f) {
522 int n; /* number of returns */ 522 int n; /* number of returns */
523 CallInfo *ci; 523 CallInfo *ci;
524 checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ 524 checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
525 L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, 525 L->ci = ci = prepCallInfo(L, func, nresults, CIST_C,
526 L->top.p + LUA_MINSTACK); 526 L->top.p + LUA_MINSTACK);
527 lua_assert(ci->top.p <= L->stack_last.p); 527 lua_assert(ci->top.p <= L->stack_last.p);
@@ -557,7 +557,7 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
557 int fsize = p->maxstacksize; /* frame size */ 557 int fsize = p->maxstacksize; /* frame size */
558 int nfixparams = p->numparams; 558 int nfixparams = p->numparams;
559 int i; 559 int i;
560 checkstackGCp(L, fsize - delta, func); 560 checkstackp(L, fsize - delta, func);
561 ci->func.p -= delta; /* restore 'func' (if vararg) */ 561 ci->func.p -= delta; /* restore 'func' (if vararg) */
562 for (i = 0; i < narg1; i++) /* move down function and arguments */ 562 for (i = 0; i < narg1; i++) /* move down function and arguments */
563 setobjs2s(L, ci->func.p + i, func + i); 563 setobjs2s(L, ci->func.p + i, func + i);
@@ -604,7 +604,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
604 int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */ 604 int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */
605 int nfixparams = p->numparams; 605 int nfixparams = p->numparams;
606 int fsize = p->maxstacksize; /* frame size */ 606 int fsize = p->maxstacksize; /* frame size */
607 checkstackGCp(L, fsize, func); 607 checkstackp(L, fsize, func);
608 L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); 608 L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize);
609 ci->u.l.savedpc = p->code; /* starting point */ 609 ci->u.l.savedpc = p->code; /* starting point */
610 for (; narg < nfixparams; narg++) 610 for (; narg < nfixparams; narg++)
diff --git a/ldo.h b/ldo.h
index 1aa446ad..b050fc08 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/lgc.c b/lgc.c
index a3094ff5..27856650 100644
--- a/lgc.c
+++ b/lgc.c
@@ -19,6 +19,7 @@
19#include "ldo.h" 19#include "ldo.h"
20#include "lfunc.h" 20#include "lfunc.h"
21#include "lgc.h" 21#include "lgc.h"
22#include "llex.h"
22#include "lmem.h" 23#include "lmem.h"
23#include "lobject.h" 24#include "lobject.h"
24#include "lstate.h" 25#include "lstate.h"
@@ -28,36 +29,18 @@
28 29
29 30
30/* 31/*
31** Maximum number of elements to sweep in each single step. 32** Number of fixed (luaC_fix) objects in a Lua state: metafield names,
32** (Large enough to dissipate fixed overheads but small enough 33** 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*/ 34*/
53#define WORK2MEM sizeof(TValue) 35#define NFIXED (TM_N + NUM_RESERVED + 2)
54 36
55 37
56/* 38/*
57** macro to adjust 'pause': 'pause' is actually used like 39** Maximum number of elements to sweep in each single step.
58** 'pause / PAUSEADJ' (value chosen by tests) 40** (Large enough to dissipate fixed overheads but small enough
41** to allow small steps for the collector.)
59*/ 42*/
60#define PAUSEADJ 100 43#define GCSWEEPMAX 20
61 44
62 45
63/* mask with all color bits */ 46/* mask with all color bits */
@@ -105,7 +88,7 @@
105#define markobjectN(g,t) { if (t) markobject(g,t); } 88#define markobjectN(g,t) { if (t) markobject(g,t); }
106 89
107static void reallymarkobject (global_State *g, GCObject *o); 90static void reallymarkobject (global_State *g, GCObject *o);
108static lu_mem atomic (lua_State *L); 91static l_obj atomic (lua_State *L);
109static void entersweep (lua_State *L); 92static void entersweep (lua_State *L);
110 93
111 94
@@ -217,7 +200,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
217 } 200 }
218 else { /* sweep phase */ 201 else { /* sweep phase */
219 lua_assert(issweepphase(g)); 202 lua_assert(issweepphase(g));
220 if (g->gckind == KGC_INC) /* incremental mode? */ 203 if (g->gckind != KGC_GEN) /* incremental mode? */
221 makewhite(g, o); /* mark 'o' as white to avoid other barriers */ 204 makewhite(g, o); /* mark 'o' as white to avoid other barriers */
222 } 205 }
223} 206}
@@ -259,6 +242,7 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
259 global_State *g = G(L); 242 global_State *g = G(L);
260 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); 243 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz));
261 GCObject *o = cast(GCObject *, p + offset); 244 GCObject *o = cast(GCObject *, p + offset);
245 g->GCdebt--;
262 o->marked = luaC_white(g); 246 o->marked = luaC_white(g);
263 o->tt = tt; 247 o->tt = tt;
264 o->next = g->allgc; 248 o->next = g->allgc;
@@ -267,6 +251,9 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
267} 251}
268 252
269 253
254/*
255** create a new collectable object with no offset.
256*/
270GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { 257GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
271 return luaC_newobjdt(L, tt, sz, 0); 258 return luaC_newobjdt(L, tt, sz, 0);
272} 259}
@@ -295,6 +282,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. 282** (only closures can), and a userdata's metatable must be a table.
296*/ 283*/
297static void reallymarkobject (global_State *g, GCObject *o) { 284static void reallymarkobject (global_State *g, GCObject *o) {
285 g->marked++;
298 switch (o->tt) { 286 switch (o->tt) {
299 case LUA_VSHRSTR: 287 case LUA_VSHRSTR:
300 case LUA_VLNGSTR: { 288 case LUA_VLNGSTR: {
@@ -342,9 +330,9 @@ static void markmt (global_State *g) {
342/* 330/*
343** mark all objects in list of being-finalized 331** mark all objects in list of being-finalized
344*/ 332*/
345static lu_mem markbeingfnz (global_State *g) { 333static l_obj markbeingfnz (global_State *g) {
346 GCObject *o; 334 GCObject *o;
347 lu_mem count = 0; 335 l_obj count = 0;
348 for (o = g->tobefnz; o != NULL; o = o->next) { 336 for (o = g->tobefnz; o != NULL; o = o->next) {
349 count++; 337 count++;
350 markobject(g, o); 338 markobject(g, o);
@@ -364,12 +352,11 @@ static lu_mem markbeingfnz (global_State *g) {
364** upvalues, as they have nothing to be checked. (If the thread gets an 352** upvalues, as they have nothing to be checked. (If the thread gets an
365** upvalue later, it will be linked in the list again.) 353** upvalue later, it will be linked in the list again.)
366*/ 354*/
367static int remarkupvals (global_State *g) { 355static l_obj remarkupvals (global_State *g) {
356 l_obj work = 0;
368 lua_State *thread; 357 lua_State *thread;
369 lua_State **p = &g->twups; 358 lua_State **p = &g->twups;
370 int work = 0; /* estimate of how much work was done here */
371 while ((thread = *p) != NULL) { 359 while ((thread = *p) != NULL) {
372 work++;
373 if (!iswhite(thread) && thread->openupval != NULL) 360 if (!iswhite(thread) && thread->openupval != NULL)
374 p = &thread->twups; /* keep marked thread with upvalues in the list */ 361 p = &thread->twups; /* keep marked thread with upvalues in the list */
375 else { /* thread is not marked or without upvalues */ 362 else { /* thread is not marked or without upvalues */
@@ -379,13 +366,13 @@ static int remarkupvals (global_State *g) {
379 thread->twups = thread; /* mark that it is out of list */ 366 thread->twups = thread; /* mark that it is out of list */
380 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { 367 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
381 lua_assert(getage(uv) <= getage(thread)); 368 lua_assert(getage(uv) <= getage(thread));
382 work++;
383 if (!iswhite(uv)) { /* upvalue already visited? */ 369 if (!iswhite(uv)) { /* upvalue already visited? */
384 lua_assert(upisopen(uv) && isgray(uv)); 370 lua_assert(upisopen(uv) && isgray(uv));
385 markvalue(g, uv->v.p); /* mark its value */ 371 markvalue(g, uv->v.p); /* mark its value */
386 } 372 }
387 } 373 }
388 } 374 }
375 work++;
389 } 376 }
390 return work; 377 return work;
391} 378}
@@ -398,10 +385,15 @@ static void cleargraylists (global_State *g) {
398 385
399 386
400/* 387/*
401** mark root set and reset all gray lists, to start a new collection 388** mark root set and reset all gray lists, to start a new collection.
389** 'marked' is initialized with the number of fixed objects in the state,
390** to count the total number of live objects during a cycle. (That is
391** the metafield names, plus the reserved words, plus "_ENV" plus the
392** memory-error message.)
402*/ 393*/
403static void restartcollection (global_State *g) { 394static void restartcollection (global_State *g) {
404 cleargraylists(g); 395 cleargraylists(g);
396 g->marked = NFIXED;
405 markobject(g, g->mainthread); 397 markobject(g, g->mainthread);
406 markvalue(g, &g->l_registry); 398 markvalue(g, &g->l_registry);
407 markmt(g); 399 markmt(g);
@@ -539,7 +531,7 @@ static void traversestrongtable (global_State *g, Table *h) {
539} 531}
540 532
541 533
542static lu_mem traversetable (global_State *g, Table *h) { 534static void traversetable (global_State *g, Table *h) {
543 const char *weakkey, *weakvalue; 535 const char *weakkey, *weakvalue;
544 const TValue *mode = gfasttm(g, h->metatable, TM_MODE); 536 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
545 markobjectN(g, h->metatable); 537 markobjectN(g, h->metatable);
@@ -556,17 +548,15 @@ static lu_mem traversetable (global_State *g, Table *h) {
556 } 548 }
557 else /* not weak */ 549 else /* not weak */
558 traversestrongtable(g, h); 550 traversestrongtable(g, h);
559 return 1 + h->alimit + 2 * allocsizenode(h);
560} 551}
561 552
562 553
563static int traverseudata (global_State *g, Udata *u) { 554static void traverseudata (global_State *g, Udata *u) {
564 int i; 555 int i;
565 markobjectN(g, u->metatable); /* mark its metatable */ 556 markobjectN(g, u->metatable); /* mark its metatable */
566 for (i = 0; i < u->nuvalue; i++) 557 for (i = 0; i < u->nuvalue; i++)
567 markvalue(g, &u->uv[i].uv); 558 markvalue(g, &u->uv[i].uv);
568 genlink(g, obj2gco(u)); 559 genlink(g, obj2gco(u));
569 return 1 + u->nuvalue;
570} 560}
571 561
572 562
@@ -575,7 +565,7 @@ static int traverseudata (global_State *g, Udata *u) {
575** arrays can be larger than needed; the extra slots are filled with 565** arrays can be larger than needed; the extra slots are filled with
576** NULL, so the use of 'markobjectN') 566** NULL, so the use of 'markobjectN')
577*/ 567*/
578static int traverseproto (global_State *g, Proto *f) { 568static void traverseproto (global_State *g, Proto *f) {
579 int i; 569 int i;
580 markobjectN(g, f->source); 570 markobjectN(g, f->source);
581 for (i = 0; i < f->sizek; i++) /* mark literals */ 571 for (i = 0; i < f->sizek; i++) /* mark literals */
@@ -586,29 +576,26 @@ static int traverseproto (global_State *g, Proto *f) {
586 markobjectN(g, f->p[i]); 576 markobjectN(g, f->p[i]);
587 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ 577 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
588 markobjectN(g, f->locvars[i].varname); 578 markobjectN(g, f->locvars[i].varname);
589 return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
590} 579}
591 580
592 581
593static int traverseCclosure (global_State *g, CClosure *cl) { 582static void traverseCclosure (global_State *g, CClosure *cl) {
594 int i; 583 int i;
595 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ 584 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
596 markvalue(g, &cl->upvalue[i]); 585 markvalue(g, &cl->upvalue[i]);
597 return 1 + cl->nupvalues;
598} 586}
599 587
600/* 588/*
601** Traverse a Lua closure, marking its prototype and its upvalues. 589** Traverse a Lua closure, marking its prototype and its upvalues.
602** (Both can be NULL while closure is being created.) 590** (Both can be NULL while closure is being created.)
603*/ 591*/
604static int traverseLclosure (global_State *g, LClosure *cl) { 592static void traverseLclosure (global_State *g, LClosure *cl) {
605 int i; 593 int i;
606 markobjectN(g, cl->p); /* mark its prototype */ 594 markobjectN(g, cl->p); /* mark its prototype */
607 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ 595 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */
608 UpVal *uv = cl->upvals[i]; 596 UpVal *uv = cl->upvals[i];
609 markobjectN(g, uv); /* mark upvalue */ 597 markobjectN(g, uv); /* mark upvalue */
610 } 598 }
611 return 1 + cl->nupvalues;
612} 599}
613 600
614 601
@@ -624,13 +611,13 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
624** (which can only happen in generational mode) or if the traverse is in 611** (which can only happen in generational mode) or if the traverse is in
625** the propagate phase (which can only happen in incremental mode). 612** the propagate phase (which can only happen in incremental mode).
626*/ 613*/
627static int traversethread (global_State *g, lua_State *th) { 614static void traversethread (global_State *g, lua_State *th) {
628 UpVal *uv; 615 UpVal *uv;
629 StkId o = th->stack.p; 616 StkId o = th->stack.p;
630 if (isold(th) || g->gcstate == GCSpropagate) 617 if (isold(th) || g->gcstate == GCSpropagate)
631 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 618 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
632 if (o == NULL) 619 if (o == NULL)
633 return 1; /* stack not completely built yet */ 620 return; /* stack not completely built yet */
634 lua_assert(g->gcstate == GCSatomic || 621 lua_assert(g->gcstate == GCSatomic ||
635 th->openupval == NULL || isintwups(th)); 622 th->openupval == NULL || isintwups(th));
636 for (; o < th->top.p; o++) /* mark live elements in the stack */ 623 for (; o < th->top.p; o++) /* mark live elements in the stack */
@@ -648,34 +635,35 @@ static int traversethread (global_State *g, lua_State *th) {
648 } 635 }
649 else if (!g->gcemergency) 636 else if (!g->gcemergency)
650 luaD_shrinkstack(th); /* do not change stack in emergency cycle */ 637 luaD_shrinkstack(th); /* do not change stack in emergency cycle */
651 return 1 + stacksize(th);
652} 638}
653 639
654 640
655/* 641/*
656** traverse one gray object, turning it to black. 642** traverse one gray object, turning it to black.
657*/ 643*/
658static lu_mem propagatemark (global_State *g) { 644static void propagatemark (global_State *g) {
659 GCObject *o = g->gray; 645 GCObject *o = g->gray;
660 nw2black(o); 646 nw2black(o);
661 g->gray = *getgclist(o); /* remove from 'gray' list */ 647 g->gray = *getgclist(o); /* remove from 'gray' list */
662 switch (o->tt) { 648 switch (o->tt) {
663 case LUA_VTABLE: return traversetable(g, gco2t(o)); 649 case LUA_VTABLE: traversetable(g, gco2t(o)); break;
664 case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); 650 case LUA_VUSERDATA: traverseudata(g, gco2u(o)); break;
665 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); 651 case LUA_VLCL: traverseLclosure(g, gco2lcl(o)); break;
666 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); 652 case LUA_VCCL: traverseCclosure(g, gco2ccl(o)); break;
667 case LUA_VPROTO: return traverseproto(g, gco2p(o)); 653 case LUA_VPROTO: traverseproto(g, gco2p(o)); break;
668 case LUA_VTHREAD: return traversethread(g, gco2th(o)); 654 case LUA_VTHREAD: traversethread(g, gco2th(o)); break;
669 default: lua_assert(0); return 0; 655 default: lua_assert(0);
670 } 656 }
671} 657}
672 658
673 659
674static lu_mem propagateall (global_State *g) { 660static l_obj propagateall (global_State *g) {
675 lu_mem tot = 0; 661 l_obj work = 0;
676 while (g->gray) 662 while (g->gray) {
677 tot += propagatemark(g); 663 propagatemark(g);
678 return tot; 664 work++;
665 }
666 return work;
679} 667}
680 668
681 669
@@ -684,10 +672,10 @@ static lu_mem propagateall (global_State *g) {
684** Repeat until it converges, that is, nothing new is marked. 'dir' 672** Repeat until it converges, that is, nothing new is marked. 'dir'
685** inverts the direction of the traversals, trying to speed up 673** inverts the direction of the traversals, trying to speed up
686** convergence on chains in the same table. 674** convergence on chains in the same table.
687**
688*/ 675*/
689static void convergeephemerons (global_State *g) { 676static l_obj convergeephemerons (global_State *g) {
690 int changed; 677 int changed;
678 l_obj work = 0;
691 int dir = 0; 679 int dir = 0;
692 do { 680 do {
693 GCObject *w; 681 GCObject *w;
@@ -702,9 +690,11 @@ static void convergeephemerons (global_State *g) {
702 propagateall(g); /* propagate changes */ 690 propagateall(g); /* propagate changes */
703 changed = 1; /* will have to revisit all ephemeron tables */ 691 changed = 1; /* will have to revisit all ephemeron tables */
704 } 692 }
693 work++;
705 } 694 }
706 dir = !dir; /* invert direction next time */ 695 dir = !dir; /* invert direction next time */
707 } while (changed); /* repeat until no more changes */ 696 } while (changed); /* repeat until no more changes */
697 return work;
708} 698}
709 699
710/* }====================================================== */ 700/* }====================================================== */
@@ -720,7 +710,8 @@ static void convergeephemerons (global_State *g) {
720/* 710/*
721** clear entries with unmarked keys from all weaktables in list 'l' 711** clear entries with unmarked keys from all weaktables in list 'l'
722*/ 712*/
723static void clearbykeys (global_State *g, GCObject *l) { 713static l_obj clearbykeys (global_State *g, GCObject *l) {
714 l_obj work = 0;
724 for (; l; l = gco2t(l)->gclist) { 715 for (; l; l = gco2t(l)->gclist) {
725 Table *h = gco2t(l); 716 Table *h = gco2t(l);
726 Node *limit = gnodelast(h); 717 Node *limit = gnodelast(h);
@@ -731,7 +722,9 @@ static void clearbykeys (global_State *g, GCObject *l) {
731 if (isempty(gval(n))) /* is entry empty? */ 722 if (isempty(gval(n))) /* is entry empty? */
732 clearkey(n); /* clear its key */ 723 clearkey(n); /* clear its key */
733 } 724 }
725 work++;
734 } 726 }
727 return work;
735} 728}
736 729
737 730
@@ -739,7 +732,8 @@ static void clearbykeys (global_State *g, GCObject *l) {
739** clear entries with unmarked values from all weaktables in list 'l' up 732** clear entries with unmarked values from all weaktables in list 'l' up
740** to element 'f' 733** to element 'f'
741*/ 734*/
742static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { 735static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
736 l_obj work = 0;
743 for (; l != f; l = gco2t(l)->gclist) { 737 for (; l != f; l = gco2t(l)->gclist) {
744 Table *h = gco2t(l); 738 Table *h = gco2t(l);
745 Node *n, *limit = gnodelast(h); 739 Node *n, *limit = gnodelast(h);
@@ -756,7 +750,9 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
756 if (isempty(gval(n))) /* is entry empty? */ 750 if (isempty(gval(n))) /* is entry empty? */
757 clearkey(n); /* clear its key */ 751 clearkey(n); /* clear its key */
758 } 752 }
753 work++;
759 } 754 }
755 return work;
760} 756}
761 757
762 758
@@ -768,6 +764,7 @@ static void freeupval (lua_State *L, UpVal *uv) {
768 764
769 765
770static void freeobj (lua_State *L, GCObject *o) { 766static void freeobj (lua_State *L, GCObject *o) {
767 G(L)->totalobjs--;
771 switch (o->tt) { 768 switch (o->tt) {
772 case LUA_VPROTO: 769 case LUA_VPROTO:
773 luaF_freeproto(L, gco2p(o)); 770 luaF_freeproto(L, gco2p(o));
@@ -817,10 +814,9 @@ static void freeobj (lua_State *L, GCObject *o) {
817** objects, where a dead object is one marked with the old (non current) 814** 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 815** white; change all non-dead objects back to white, preparing for next
819** collection cycle. Return where to continue the traversal or NULL if 816** collection cycle. Return where to continue the traversal or NULL if
820** list is finished. ('*countout' gets the number of elements traversed.) 817** list is finished.
821*/ 818*/
822static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, 819static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) {
823 int *countout) {
824 global_State *g = G(L); 820 global_State *g = G(L);
825 int ow = otherwhite(g); 821 int ow = otherwhite(g);
826 int i; 822 int i;
@@ -837,8 +833,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
837 p = &curr->next; /* go to next element */ 833 p = &curr->next; /* go to next element */
838 } 834 }
839 } 835 }
840 if (countout)
841 *countout = i; /* number of elements traversed */
842 return (*p == NULL) ? NULL : p; 836 return (*p == NULL) ? NULL : p;
843} 837}
844 838
@@ -849,7 +843,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
849static GCObject **sweeptolive (lua_State *L, GCObject **p) { 843static GCObject **sweeptolive (lua_State *L, GCObject **p) {
850 GCObject **old = p; 844 GCObject **old = p;
851 do { 845 do {
852 p = sweeplist(L, p, 1, NULL); 846 p = sweeplist(L, p, 1);
853 } while (p == old); 847 } while (p == old);
854 return p; 848 return p;
855} 849}
@@ -868,11 +862,8 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) {
868*/ 862*/
869static void checkSizes (lua_State *L, global_State *g) { 863static void checkSizes (lua_State *L, global_State *g) {
870 if (!g->gcemergency) { 864 if (!g->gcemergency) {
871 if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ 865 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); 866 luaS_resize(L, g->strt.size / 2);
874 g->GCestimate += g->GCdebt - olddebt; /* correct estimate */
875 }
876 } 867 }
877} 868}
878 869
@@ -931,18 +922,6 @@ static void GCTM (lua_State *L) {
931 922
932 923
933/* 924/*
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 925** call all pending finalizers
947*/ 926*/
948static void callallpendingfinalizers (lua_State *L) { 927static void callallpendingfinalizers (lua_State *L) {
@@ -1050,20 +1029,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
1050 1029
1051/* 1030/*
1052** Set the "time" to wait before starting a new GC cycle; cycle will 1031** Set the "time" to wait before starting a new GC cycle; cycle will
1053** start when memory use hits the threshold of ('estimate' * pause / 1032** start when number of objects in use hits the threshold of
1054** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, 1033** approximately (marked * pause / 100).
1055** because Lua cannot even start with less than PAUSEADJ bytes).
1056*/ 1034*/
1057static void setpause (global_State *g) { 1035static void setpause (global_State *g) {
1058 l_mem threshold, debt; 1036 l_obj threshold = applygcparam(g, gcpause, g->marked);
1059 int pause = getgcparam(g->gcpause); 1037 l_obj debt = threshold - gettotalobjs(g);
1060 l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ 1038 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); 1039 luaE_setdebt(g, debt);
1068} 1040}
1069 1041
@@ -1303,18 +1275,17 @@ static void atomic2gen (lua_State *L, global_State *g) {
1303 sweep2old(L, &g->tobefnz); 1275 sweep2old(L, &g->tobefnz);
1304 1276
1305 g->gckind = KGC_GEN; 1277 g->gckind = KGC_GEN;
1306 g->lastatomic = 0; 1278 g->GClastmajor = gettotalobjs(g); /* base for memory control */
1307 g->GCestimate = gettotalbytes(g); /* base for memory control */
1308 finishgencycle(L, g); 1279 finishgencycle(L, g);
1309} 1280}
1310 1281
1311 1282
1312/* 1283/*
1313** Set debt for the next minor collection, which will happen when 1284** Set debt for the next minor collection, which will happen when
1314** memory grows 'genminormul'%. 1285** total number of objects grows 'genminormul'%.
1315*/ 1286*/
1316static void setminordebt (global_State *g) { 1287static void setminordebt (global_State *g) {
1317 luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); 1288 luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g)));
1318} 1289}
1319 1290
1320 1291
@@ -1324,14 +1295,12 @@ static void setminordebt (global_State *g) {
1324** are cleared. Then, turn all objects into old and finishes the 1295** are cleared. Then, turn all objects into old and finishes the
1325** collection. 1296** collection.
1326*/ 1297*/
1327static lu_mem entergen (lua_State *L, global_State *g) { 1298static void entergen (lua_State *L, global_State *g) {
1328 lu_mem numobjs;
1329 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ 1299 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */
1330 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1300 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1331 numobjs = atomic(L); /* propagates all and then do the atomic stuff */ 1301 atomic(L); /* propagates all and then do the atomic stuff */
1332 atomic2gen(L, g); 1302 atomic2gen(L, g);
1333 setminordebt(g); /* set debt assuming next cycle will be minor */ 1303 setminordebt(g); /* set debt assuming next cycle will be minor */
1334 return numobjs;
1335} 1304}
1336 1305
1337 1306
@@ -1348,7 +1317,6 @@ static void enterinc (global_State *g) {
1348 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1317 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1349 g->gcstate = GCSpause; 1318 g->gcstate = GCSpause;
1350 g->gckind = KGC_INC; 1319 g->gckind = KGC_INC;
1351 g->lastatomic = 0;
1352} 1320}
1353 1321
1354 1322
@@ -1357,111 +1325,77 @@ static void enterinc (global_State *g) {
1357*/ 1325*/
1358void luaC_changemode (lua_State *L, int newmode) { 1326void luaC_changemode (lua_State *L, int newmode) {
1359 global_State *g = G(L); 1327 global_State *g = G(L);
1360 if (newmode != g->gckind) { 1328 if (newmode != g->gckind) { /* does it need to change? */
1361 if (newmode == KGC_GEN) /* entering generational mode? */ 1329 if (newmode == KGC_INC) { /* entering incremental mode? */
1330 if (g->gckind == KGC_GENMAJOR)
1331 g->gckind = KGC_INC; /* already incremental but in name */
1332 else
1333 enterinc(g); /* entering incremental mode */
1334 }
1335 else {
1336 lua_assert(newmode == KGC_GEN);
1362 entergen(L, g); 1337 entergen(L, g);
1363 else 1338 }
1364 enterinc(g); /* entering incremental mode */
1365 } 1339 }
1366 g->lastatomic = 0;
1367} 1340}
1368 1341
1369 1342
1370/* 1343/*
1371** Does a full collection in generational mode. 1344** Does a full collection in generational mode.
1372*/ 1345*/
1373static lu_mem fullgen (lua_State *L, global_State *g) { 1346static void fullgen (lua_State *L, global_State *g) {
1374 enterinc(g); 1347 enterinc(g);
1375 return entergen(L, g); 1348 entergen(L, g);
1376} 1349}
1377 1350
1378 1351
1379/* 1352/*
1380** Does a major collection after last collection was a "bad collection". 1353** Does a major collector up to the atomic phase and then either
1381** 1354** returns to minor collections or stays doing major ones. If the
1382** When the program is building a big structure, it allocates lots of 1355** number of objects collected this time (numobjs - marked) is more than
1383** memory but generates very little garbage. In those scenarios, 1356** half the number of objects created since the last major collection
1384** the generational mode just wastes time doing small collections, and 1357** (numobjs - lastmajor), it goes back to minor collections.
1385** major collections are frequently what we call a "bad collection", a 1358*/
1386** collection that frees too few objects. To avoid the cost of switching 1359static void genmajorstep (lua_State *L, global_State *g) {
1387** between generational mode and the incremental mode needed for full 1360 l_obj lastmajor = g->GClastmajor; /* count from last collection */
1388** (major) collections, the collector tries to stay in incremental mode 1361 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 */ 1362 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1406 newatomic = atomic(L); /* mark everybody */ 1363 atomic(L); /* mark everybody */
1407 if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ 1364 if ((numobjs - g->marked) > ((numobjs - lastmajor) >> 1)) {
1408 atomic2gen(L, g); /* return to generational mode */ 1365 atomic2gen(L, g); /* return to generational mode */
1409 setminordebt(g); 1366 setminordebt(g);
1410 } 1367 }
1411 else { /* another bad collection; stay in incremental mode */ 1368 else { /* bad collection; stay in major mode */
1412 g->GCestimate = gettotalbytes(g); /* first estimate */;
1413 entersweep(L); 1369 entersweep(L);
1414 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1370 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1415 setpause(g); 1371 setpause(g);
1416 g->lastatomic = newatomic; 1372 g->GClastmajor = gettotalobjs(g);
1417 } 1373 }
1418} 1374}
1419 1375
1420 1376
1421/* 1377/*
1422** Does a generational "step". 1378** Does a generational "step". If the total number of objects grew
1423** Usually, this means doing a minor collection and setting the debt to 1379** more than 'majormul'% since the last major collection, does a
1424** make another collection when memory grows 'genminormul'% larger. 1380** major collection. Otherwise, does a minor collection. The test
1425** 1381** ('GCdebt' != 0) avoids major collections when the step originated from
1426** However, there are exceptions. If memory grows 'genmajormul'% 1382** 'collectgarbage("step")'.
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*/ 1383*/
1440static void genstep (lua_State *L, global_State *g) { 1384static void genstep (lua_State *L, global_State *g) {
1441 if (g->lastatomic != 0) /* last collection was a bad one? */ 1385 l_obj majorbase = g->GClastmajor; /* count after last major collection */
1442 stepgenfull(L, g); /* do a full step */ 1386 l_obj majorinc = applygcparam(g, genmajormul, majorbase);
1443 else { 1387 if (g->GCdebt != 0 && gettotalobjs(g) > majorbase + majorinc) {
1444 lu_mem majorbase = g->GCestimate; /* memory after last major collection */ 1388 /* do a major collection */
1445 lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); 1389 enterinc(g);
1446 if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { 1390 g->gckind = KGC_GENMAJOR;
1447 lu_mem numobjs = fullgen(L, g); /* do a major collection */ 1391 genmajorstep(L, g);
1448 if (gettotalbytes(g) < majorbase + (majorinc / 2)) { 1392 }
1449 /* collected at least half of memory growth since last major 1393 else { /* regular case; do a minor collection */
1450 collection; keep doing minor collections. */ 1394 g->marked = 0;
1451 lua_assert(g->lastatomic == 0); 1395 youngcollection(L, g);
1452 } 1396 setminordebt(g);
1453 else { /* bad collection */ 1397 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 } 1398 }
1464 lua_assert(isdecGCmodegen(g));
1465} 1399}
1466 1400
1467/* }====================================================== */ 1401/* }====================================================== */
@@ -1520,9 +1454,9 @@ void luaC_freeallobjects (lua_State *L) {
1520} 1454}
1521 1455
1522 1456
1523static lu_mem atomic (lua_State *L) { 1457static l_obj atomic (lua_State *L) {
1458 l_obj work = 0;
1524 global_State *g = G(L); 1459 global_State *g = G(L);
1525 lu_mem work = 0;
1526 GCObject *origweak, *origall; 1460 GCObject *origweak, *origall;
1527 GCObject *grayagain = g->grayagain; /* save original list */ 1461 GCObject *grayagain = g->grayagain; /* save original list */
1528 g->grayagain = NULL; 1462 g->grayagain = NULL;
@@ -1539,50 +1473,44 @@ static lu_mem atomic (lua_State *L) {
1539 work += propagateall(g); /* propagate changes */ 1473 work += propagateall(g); /* propagate changes */
1540 g->gray = grayagain; 1474 g->gray = grayagain;
1541 work += propagateall(g); /* traverse 'grayagain' list */ 1475 work += propagateall(g); /* traverse 'grayagain' list */
1542 convergeephemerons(g); 1476 work += convergeephemerons(g);
1543 /* at this point, all strongly accessible objects are marked. */ 1477 /* at this point, all strongly accessible objects are marked. */
1544 /* Clear values from weak tables, before checking finalizers */ 1478 /* Clear values from weak tables, before checking finalizers */
1545 clearbyvalues(g, g->weak, NULL); 1479 work += clearbyvalues(g, g->weak, NULL);
1546 clearbyvalues(g, g->allweak, NULL); 1480 work += clearbyvalues(g, g->allweak, NULL);
1547 origweak = g->weak; origall = g->allweak; 1481 origweak = g->weak; origall = g->allweak;
1548 separatetobefnz(g, 0); /* separate objects to be finalized */ 1482 separatetobefnz(g, 0); /* separate objects to be finalized */
1549 work += markbeingfnz(g); /* mark objects that will be finalized */ 1483 work += markbeingfnz(g); /* mark objects that will be finalized */
1550 work += propagateall(g); /* remark, to propagate 'resurrection' */ 1484 work += propagateall(g); /* remark, to propagate 'resurrection' */
1551 convergeephemerons(g); 1485 work += convergeephemerons(g);
1552 /* at this point, all resurrected objects are marked. */ 1486 /* at this point, all resurrected objects are marked. */
1553 /* remove dead objects from weak tables */ 1487 /* remove dead objects from weak tables */
1554 clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ 1488 work += clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */
1555 clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ 1489 work += clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */
1556 /* clear values from resurrected weak tables */ 1490 /* clear values from resurrected weak tables */
1557 clearbyvalues(g, g->weak, origweak); 1491 work += clearbyvalues(g, g->weak, origweak);
1558 clearbyvalues(g, g->allweak, origall); 1492 work += clearbyvalues(g, g->allweak, origall);
1559 luaS_clearcache(g); 1493 luaS_clearcache(g);
1560 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1494 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
1561 lua_assert(g->gray == NULL); 1495 lua_assert(g->gray == NULL);
1562 return work; /* estimate of slots marked by 'atomic' */ 1496 return work;
1563} 1497}
1564 1498
1565 1499
1566static int sweepstep (lua_State *L, global_State *g, 1500static void sweepstep (lua_State *L, global_State *g,
1567 int nextstate, GCObject **nextlist) { 1501 int nextstate, GCObject **nextlist) {
1568 if (g->sweepgc) { 1502 if (g->sweepgc)
1569 l_mem olddebt = g->GCdebt; 1503 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 */ 1504 else { /* enter next state */
1576 g->gcstate = nextstate; 1505 g->gcstate = nextstate;
1577 g->sweepgc = nextlist; 1506 g->sweepgc = nextlist;
1578 return 0; /* no work done */
1579 } 1507 }
1580} 1508}
1581 1509
1582 1510
1583static lu_mem singlestep (lua_State *L) { 1511static l_obj singlestep (lua_State *L) {
1584 global_State *g = G(L); 1512 global_State *g = G(L);
1585 lu_mem work; 1513 l_obj work;
1586 lua_assert(!g->gcstopem); /* collector is not reentrant */ 1514 lua_assert(!g->gcstopem); /* collector is not reentrant */
1587 g->gcstopem = 1; /* no emergency collections while collecting */ 1515 g->gcstopem = 1; /* no emergency collections while collecting */
1588 switch (g->gcstate) { 1516 switch (g->gcstate) {
@@ -1597,26 +1525,30 @@ static lu_mem singlestep (lua_State *L) {
1597 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1525 g->gcstate = GCSenteratomic; /* finish propagate phase */
1598 work = 0; 1526 work = 0;
1599 } 1527 }
1600 else 1528 else {
1601 work = propagatemark(g); /* traverse one gray object */ 1529 propagatemark(g); /* traverse one gray object */
1530 work = 1;
1531 }
1602 break; 1532 break;
1603 } 1533 }
1604 case GCSenteratomic: { 1534 case GCSenteratomic: {
1605 work = atomic(L); /* work is what was traversed by 'atomic' */ 1535 work = atomic(L);
1606 entersweep(L); 1536 entersweep(L);
1607 g->GCestimate = gettotalbytes(g); /* first estimate */;
1608 break; 1537 break;
1609 } 1538 }
1610 case GCSswpallgc: { /* sweep "regular" objects */ 1539 case GCSswpallgc: { /* sweep "regular" objects */
1611 work = sweepstep(L, g, GCSswpfinobj, &g->finobj); 1540 sweepstep(L, g, GCSswpfinobj, &g->finobj);
1541 work = GCSWEEPMAX;
1612 break; 1542 break;
1613 } 1543 }
1614 case GCSswpfinobj: { /* sweep objects with finalizers */ 1544 case GCSswpfinobj: { /* sweep objects with finalizers */
1615 work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1545 sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1546 work = GCSWEEPMAX;
1616 break; 1547 break;
1617 } 1548 }
1618 case GCSswptobefnz: { /* sweep objects to be finalized */ 1549 case GCSswptobefnz: { /* sweep objects to be finalized */
1619 work = sweepstep(L, g, GCSswpend, NULL); 1550 sweepstep(L, g, GCSswpend, NULL);
1551 work = GCSWEEPMAX;
1620 break; 1552 break;
1621 } 1553 }
1622 case GCSswpend: { /* finish sweeps */ 1554 case GCSswpend: { /* finish sweeps */
@@ -1625,10 +1557,11 @@ static lu_mem singlestep (lua_State *L) {
1625 work = 0; 1557 work = 0;
1626 break; 1558 break;
1627 } 1559 }
1628 case GCScallfin: { /* call remaining finalizers */ 1560 case GCScallfin: { /* call finalizers */
1629 if (g->tobefnz && !g->gcemergency) { 1561 if (g->tobefnz && !g->gcemergency) {
1630 g->gcstopem = 0; /* ok collections during finalizers */ 1562 g->gcstopem = 0; /* ok collections during finalizers */
1631 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; 1563 GCTM(L); /* call one finalizer */
1564 work = 1;
1632 } 1565 }
1633 else { /* emergency mode or no more finalizers */ 1566 else { /* emergency mode or no more finalizers */
1634 g->gcstate = GCSpause; /* finish collection */ 1567 g->gcstate = GCSpause; /* finish collection */
@@ -1663,20 +1596,16 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1663** controls when next step will be performed. 1596** controls when next step will be performed.
1664*/ 1597*/
1665static void incstep (lua_State *L, global_State *g) { 1598static void incstep (lua_State *L, global_State *g) {
1666 int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ 1599 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1667 l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; 1600 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) */ 1601 do { /* repeat until pause or enough "credit" (negative debt) */
1672 lu_mem work = singlestep(L); /* perform one single step */ 1602 l_obj work = singlestep(L); /* perform one single step */
1673 debt -= work; 1603 work2do -= work;
1674 } while (debt > -stepsize && g->gcstate != GCSpause); 1604 } while (work2do > 0 && g->gcstate != GCSpause);
1675 if (g->gcstate == GCSpause) 1605 if (g->gcstate == GCSpause)
1676 setpause(g); /* pause until next cycle */ 1606 setpause(g); /* pause until next cycle */
1677 else { 1607 else {
1678 debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ 1608 luaE_setdebt(g, stepsize);
1679 luaE_setdebt(g, debt);
1680 } 1609 }
1681} 1610}
1682 1611
@@ -1687,13 +1616,21 @@ static void incstep (lua_State *L, global_State *g) {
1687*/ 1616*/
1688void luaC_step (lua_State *L) { 1617void luaC_step (lua_State *L) {
1689 global_State *g = G(L); 1618 global_State *g = G(L);
1619 lua_assert(!g->gcemergency);
1690 if (!gcrunning(g)) /* not running? */ 1620 if (!gcrunning(g)) /* not running? */
1691 luaE_setdebt(g, -2000); 1621 luaE_setdebt(g, 2000);
1692 else { 1622 else {
1693 if(isdecGCmodegen(g)) 1623 switch (g->gckind) {
1694 genstep(L, g); 1624 case KGC_INC:
1695 else 1625 incstep(L, g);
1696 incstep(L, g); 1626 break;
1627 case KGC_GEN:
1628 genstep(L, g);
1629 break;
1630 case KGC_GENMAJOR:
1631 genmajorstep(L, g);
1632 break;
1633 }
1697 } 1634 }
1698} 1635}
1699 1636
@@ -1711,8 +1648,8 @@ static void fullinc (lua_State *L, global_State *g) {
1711 /* finish any pending sweep phase to start a new cycle */ 1648 /* finish any pending sweep phase to start a new cycle */
1712 luaC_runtilstate(L, bitmask(GCSpause)); 1649 luaC_runtilstate(L, bitmask(GCSpause));
1713 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ 1650 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1714 /* estimate must be correct after a full GC cycle */ 1651 /* 'marked' must be correct after a full GC cycle */
1715 lua_assert(g->GCestimate == gettotalbytes(g)); 1652 lua_assert(g->marked == gettotalobjs(g));
1716 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1653 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1717 setpause(g); 1654 setpause(g);
1718} 1655}
@@ -1727,10 +1664,10 @@ void luaC_fullgc (lua_State *L, int isemergency) {
1727 global_State *g = G(L); 1664 global_State *g = G(L);
1728 lua_assert(!g->gcemergency); 1665 lua_assert(!g->gcemergency);
1729 g->gcemergency = isemergency; /* set flag */ 1666 g->gcemergency = isemergency; /* set flag */
1730 if (g->gckind == KGC_INC) 1667 if (g->gckind == KGC_GEN)
1731 fullinc(L, g);
1732 else
1733 fullgen(L, g); 1668 fullgen(L, g);
1669 else
1670 fullinc(L, g);
1734 g->gcemergency = 0; 1671 g->gcemergency = 0;
1735} 1672}
1736 1673
diff --git a/lgc.h b/lgc.h
index c960e706..c8f7c6e6 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 52a32f92..246dca8b 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/lmem.c b/lmem.c
index 9029d588..66e2b92b 100644
--- a/lmem.c
+++ b/lmem.c
@@ -133,7 +133,7 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) {
133 global_State *g = G(L); 133 global_State *g = G(L);
134 lua_assert((osize == 0) == (block == NULL)); 134 lua_assert((osize == 0) == (block == NULL));
135 (*g->frealloc)(g->ud, block, osize, 0); 135 (*g->frealloc)(g->ud, block, osize, 0);
136 g->GCdebt -= osize; 136 g->totalbytes -= osize;
137} 137}
138 138
139 139
@@ -167,10 +167,10 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
167 if (l_unlikely(newblock == NULL && nsize > 0)) { 167 if (l_unlikely(newblock == NULL && nsize > 0)) {
168 newblock = tryagain(L, block, osize, nsize); 168 newblock = tryagain(L, block, osize, nsize);
169 if (newblock == NULL) /* still no memory? */ 169 if (newblock == NULL) /* still no memory? */
170 return NULL; /* do not update 'GCdebt' */ 170 return NULL; /* do not update 'totalbytes' */
171 } 171 }
172 lua_assert((nsize == 0) == (newblock == NULL)); 172 lua_assert((nsize == 0) == (newblock == NULL));
173 g->GCdebt = (g->GCdebt + nsize) - osize; 173 g->totalbytes += nsize - osize;
174 return newblock; 174 return newblock;
175} 175}
176 176
@@ -195,7 +195,7 @@ void *luaM_malloc_ (lua_State *L, size_t size, int tag) {
195 if (newblock == NULL) 195 if (newblock == NULL)
196 luaM_error(L); 196 luaM_error(L);
197 } 197 }
198 g->GCdebt += size; 198 g->totalbytes += size;
199 return newblock; 199 return newblock;
200 } 200 }
201} 201}
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/lstate.c b/lstate.c
index 1fbefb4b..bee3bf66 100644
--- a/lstate.c
+++ b/lstate.c
@@ -83,15 +83,15 @@ static unsigned int luai_makeseed (lua_State *L) {
83 83
84 84
85/* 85/*
86** set GCdebt to a new value keeping the value (totalbytes + GCdebt) 86** set GCdebt to a new value keeping the value (totalobjs + GCdebt)
87** invariant (and avoiding underflows in 'totalbytes') 87** invariant (and avoiding underflows in 'totalobjs')
88*/ 88*/
89void luaE_setdebt (global_State *g, l_mem debt) { 89void luaE_setdebt (global_State *g, l_obj debt) {
90 l_mem tb = gettotalbytes(g); 90 l_obj tb = gettotalobjs(g);
91 lua_assert(tb > 0); 91 lua_assert(tb > 0);
92 if (debt < tb - MAX_LMEM) 92 if (debt > MAX_LOBJ - tb)
93 debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ 93 debt = MAX_LOBJ - tb; /* will make 'totalobjs == MAX_LMEM' */
94 g->totalbytes = tb - debt; 94 g->totalobjs = tb + debt;
95 g->GCdebt = debt; 95 g->GCdebt = debt;
96} 96}
97 97
@@ -278,7 +278,8 @@ static void close_state (lua_State *L) {
278 } 278 }
279 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); 279 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
280 freestack(L); 280 freestack(L);
281 lua_assert(gettotalbytes(g) == sizeof(LG)); 281 lua_assert(g->totalbytes == sizeof(LG));
282 lua_assert(gettotalobjs(g) == 1);
282 (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ 283 (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
283} 284}
284 285
@@ -387,14 +388,15 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
387 g->weak = g->ephemeron = g->allweak = NULL; 388 g->weak = g->ephemeron = g->allweak = NULL;
388 g->twups = NULL; 389 g->twups = NULL;
389 g->totalbytes = sizeof(LG); 390 g->totalbytes = sizeof(LG);
391 g->totalobjs = 1;
392 g->marked = 0;
390 g->GCdebt = 0; 393 g->GCdebt = 0;
391 g->lastatomic = 0;
392 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ 394 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
393 setgcparam(g->gcpause, LUAI_GCPAUSE); 395 setgcparam(g, gcpause, LUAI_GCPAUSE);
394 setgcparam(g->gcstepmul, LUAI_GCMUL); 396 setgcparam(g, gcstepmul, LUAI_GCMUL);
395 g->gcstepsize = LUAI_GCSTEPSIZE; 397 g->gcstepsize = LUAI_GCSTEPSIZE;
396 setgcparam(g->genmajormul, LUAI_GENMAJORMUL); 398 setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
397 g->genminormul = LUAI_GENMINORMUL; 399 setgcparam(g, genminormul, LUAI_GENMINORMUL);
398 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 400 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
399 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 401 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
400 /* memory allocation error: free partial state */ 402 /* memory allocation error: free partial state */
diff --git a/lstate.h b/lstate.h
index 8bf6600e..50273295 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_freeCI (lua_State *L); 402LUAI_FUNC void luaE_freeCI (lua_State *L);
diff --git a/ltable.c b/ltable.c
index cc7993e0..485563f3 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*/
@@ -367,8 +388,15 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
367 388
368 389
369static void freehash (lua_State *L, Table *t) { 390static void freehash (lua_State *L, Table *t) {
370 if (!isdummy(t)) 391 if (!isdummy(t)) {
371 luaM_freearray(L, t->node, cast_sizet(sizenode(t))); 392 size_t bsize = sizenode(t) * sizeof(Node); /* 'node' size in bytes */
393 char *arr = cast_charp(t->node);
394 if (haslastfree(t)) {
395 bsize += sizeof(Limbox);
396 arr -= sizeof(Limbox);
397 }
398 luaM_freearray(L, arr, bsize);
399 }
372} 400}
373 401
374 402
@@ -479,7 +507,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
479 if (size == 0) { /* no elements to hash part? */ 507 if (size == 0) { /* no elements to hash part? */
480 t->node = cast(Node *, dummynode); /* use common 'dummynode' */ 508 t->node = cast(Node *, dummynode); /* use common 'dummynode' */
481 t->lsizenode = 0; 509 t->lsizenode = 0;
482 t->lastfree = NULL; /* signal that it is using dummy node */ 510 setdummy(t); /* signal that it is using dummy node */
483 } 511 }
484 else { 512 else {
485 int i; 513 int i;
@@ -487,15 +515,22 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
487 if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) 515 if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE)
488 luaG_runerror(L, "table overflow"); 516 luaG_runerror(L, "table overflow");
489 size = twoto(lsize); 517 size = twoto(lsize);
490 t->node = luaM_newvector(L, size, Node); 518 if (lsize <= LLIMFORLAST) /* no 'lastfree' field? */
519 t->node = luaM_newvector(L, size, Node);
520 else {
521 size_t bsize = size * sizeof(Node) + sizeof(Limbox);
522 char *node = luaM_newblock(L, bsize);
523 t->node = cast(Node *, node + sizeof(Limbox));
524 *getlastfree(t) = size; /* all positions are free */
525 }
526 t->lsizenode = cast_byte(lsize);
527 setnodummy(t);
491 for (i = 0; i < cast_int(size); i++) { 528 for (i = 0; i < cast_int(size); i++) {
492 Node *n = gnode(t, i); 529 Node *n = gnode(t, i);
493 gnext(n) = 0; 530 gnext(n) = 0;
494 setnilkey(n); 531 setnilkey(n);
495 setempty(gval(n)); 532 setempty(gval(n));
496 } 533 }
497 t->lsizenode = cast_byte(lsize);
498 t->lastfree = gnode(t, size); /* all positions are free */
499 } 534 }
500} 535}
501 536
@@ -520,18 +555,21 @@ static void reinsert (lua_State *L, Table *ot, Table *t) {
520 555
521 556
522/* 557/*
523** Exchange the hash part of 't1' and 't2'. 558** Exchange the hash part of 't1' and 't2'. (In 'flags', only the
559** dummy bit must be exchanged: The 'isrealasize' is not related
560** to the hash part, and the metamethod bits do not change during
561** a resize, so the "real" table can keep their values.)
524*/ 562*/
525static void exchangehashpart (Table *t1, Table *t2) { 563static void exchangehashpart (Table *t1, Table *t2) {
526 lu_byte lsizenode = t1->lsizenode; 564 lu_byte lsizenode = t1->lsizenode;
527 Node *node = t1->node; 565 Node *node = t1->node;
528 Node *lastfree = t1->lastfree; 566 int bitdummy1 = t1->flags & BITDUMMY;
529 t1->lsizenode = t2->lsizenode; 567 t1->lsizenode = t2->lsizenode;
530 t1->node = t2->node; 568 t1->node = t2->node;
531 t1->lastfree = t2->lastfree; 569 t1->flags = (t1->flags & NOTBITDUMMY) | (t2->flags & BITDUMMY);
532 t2->lsizenode = lsizenode; 570 t2->lsizenode = lsizenode;
533 t2->node = node; 571 t2->node = node;
534 t2->lastfree = lastfree; 572 t2->flags = (t2->flags & NOTBITDUMMY) | bitdummy1;
535} 573}
536 574
537 575
@@ -555,6 +593,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
555 unsigned int oldasize = setlimittosize(t); 593 unsigned int oldasize = setlimittosize(t);
556 TValue *newarray; 594 TValue *newarray;
557 /* create new hash part with appropriate size into 'newt' */ 595 /* create new hash part with appropriate size into 'newt' */
596 newt.flags = 0;
558 setnodevector(L, &newt, nhsize); 597 setnodevector(L, &newt, nhsize);
559 if (newasize < oldasize) { /* will array shrink? */ 598 if (newasize < oldasize) { /* will array shrink? */
560 t->alimit = newasize; /* pretend array has new size... */ 599 t->alimit = newasize; /* pretend array has new size... */
@@ -641,11 +680,22 @@ void luaH_free (lua_State *L, Table *t) {
641 680
642 681
643static Node *getfreepos (Table *t) { 682static Node *getfreepos (Table *t) {
644 if (!isdummy(t)) { 683 if (haslastfree(t)) { /* does it have 'lastfree' information? */
645 while (t->lastfree > t->node) { 684 /* look for a spot before 'lastfree', updating 'lastfree' */
646 t->lastfree--; 685 while (*getlastfree(t) > 0) {
647 if (keyisnil(t->lastfree)) 686 Node *free = gnode(t, --(*getlastfree(t)));
648 return t->lastfree; 687 if (keyisnil(free))
688 return free;
689 }
690 }
691 else { /* no 'lastfree' information */
692 if (!isdummy(t)) {
693 int i = sizenode(t);
694 while (i--) { /* do a linear search */
695 Node *free = gnode(t, i);
696 if (keyisnil(free))
697 return free;
698 }
649 } 699 }
650 } 700 }
651 return NULL; /* could not find a free place */ 701 return NULL; /* could not find a free place */
diff --git a/ltable.h b/ltable.h
index 75dd9e26..dce8c2f7 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/ltests.c b/ltests.c
index 4a0a6af1..e2e0d983 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;
@@ -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
@@ -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..45d5beba 100644
--- a/ltests.h
+++ b/ltests.h
@@ -103,8 +103,8 @@ LUA_API void *debug_realloc (void *ud, void *block,
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() lua_newstate(debug_realloc, &l_memcontrol)
106#define luaL_openlibs(L) \ 106#define luai_openlibs(L) \
107 { (luaL_openlibs)(L); \ 107 { luaL_openlibs(L); \
108 luaL_requiref(L, "T", luaB_opentests, 1); \ 108 luaL_requiref(L, "T", luaB_opentests, 1); \
109 lua_pop(L, 1); } 109 lua_pop(L, 1); }
110#endif 110#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 c309e2ae..82a26a96 100644
--- a/ltm.h
+++ b/ltm.h
@@ -49,8 +49,8 @@ typedef enum {
49/* 49/*
50** Mask with 1 in all fast-access methods. A 1 in any of these bits 50** Mask with 1 in all fast-access methods. A 1 in any of these bits
51** in the flag of a (meta)table means the metatable does not have the 51** in the flag of a (meta)table means the metatable does not have the
52** corresponding metamethod field. (Bit 7 of the flag is used for 52** corresponding metamethod field. (Bit 6 of the flag indicates that
53** 'isrealasize'.) 53** the table is using the dummy node; bit 7 is used for 'isrealasize'.)
54*/ 54*/
55#define maskflags (~(~0u << (TM_EQ + 1))) 55#define maskflags (~(~0u << (TM_EQ + 1)))
56 56
diff --git a/lua.c b/lua.c
index 715430a0..af20754e 100644
--- a/lua.c
+++ b/lua.c
@@ -609,6 +609,10 @@ static void doREPL (lua_State *L) {
609 609
610/* }================================================================== */ 610/* }================================================================== */
611 611
612#if !defined(luai_openlibs)
613#define luai_openlibs(L) luaL_openlibs(L)
614#endif
615
612 616
613/* 617/*
614** Main body of stand-alone interpreter (to be called in protected mode). 618** Main body of stand-alone interpreter (to be called in protected mode).
@@ -631,7 +635,7 @@ static int pmain (lua_State *L) {
631 lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ 635 lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
632 lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); 636 lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
633 } 637 }
634 luaL_openlibs(L); /* open standard libraries */ 638 luai_openlibs(L); /* open standard libraries */
635 createargtable(L, argv, argc, script); /* create table 'arg' */ 639 createargtable(L, argv, argc, script); /* create table 'arg' */
636 lua_gc(L, LUA_GCRESTART); /* start GC... */ 640 lua_gc(L, LUA_GCRESTART); /* start GC... */
637 lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ 641 lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */
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/testes/api.lua b/testes/api.lua
index bd85a923..f8e36ae3 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -1039,10 +1039,12 @@ assert(a == nil and b == 2) -- 2 == run-time error
1039a, b, c = T.doremote(L1, "return a+") 1039a, b, c = T.doremote(L1, "return a+")
1040assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error 1040assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
1041 1041
1042T.loadlib(L1) 1042T.loadlib(L1, 2) -- load only 'package'
1043a, b, c = T.doremote(L1, [[ 1043a, b, c = T.doremote(L1, [[
1044 string = require'string' 1044 string = require'string'
1045 a = require'_G'; assert(a == _G and require("_G") == a) 1045 local initialG = _G -- not loaded yet
1046 local a = require'_G'; assert(a == _G and require("_G") == a)
1047 assert(initialG == nil and io == nil) -- now we have 'assert'
1046 io = require'io'; assert(type(io.read) == "function") 1048 io = require'io'; assert(type(io.read) == "function")
1047 assert(require("io") == io) 1049 assert(require("io") == io)
1048 a = require'table'; assert(type(a.insert) == "function") 1050 a = require'table'; assert(type(a.insert) == "function")
@@ -1056,7 +1058,7 @@ T.closestate(L1);
1056 1058
1057 1059
1058L1 = T.newstate() 1060L1 = T.newstate()
1059T.loadlib(L1) 1061T.loadlib(L1, 0)
1060T.doremote(L1, "a = {}") 1062T.doremote(L1, "a = {}")
1061T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1; 1063T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
1062 settable -3]]) 1064 settable -3]])
@@ -1436,10 +1438,10 @@ end
1436 1438
1437do -- garbage collection with no extra memory 1439do -- garbage collection with no extra memory
1438 local L = T.newstate() 1440 local L = T.newstate()
1439 T.loadlib(L) 1441 T.loadlib(L, 1 | 2) -- load _G and 'package'
1440 local res = (T.doremote(L, [[ 1442 local res = (T.doremote(L, [[
1441 _ENV = require"_G" 1443 _ENV = _G
1442 local T = require"T" 1444 assert(string == nil)
1443 local a = {} 1445 local a = {}
1444 for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table 1446 for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table
1445 local stsize, stuse = T.querystr() 1447 local stsize, stuse = T.querystr()
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 15fccc30..f05672a5 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -694,7 +694,7 @@ else
694 694
695 T.testC(state, "settop 0") 695 T.testC(state, "settop 0")
696 696
697 T.loadlib(state) 697 T.loadlib(state, 1 | 2) -- load _G and 'package'
698 698
699 assert(T.doremote(state, [[ 699 assert(T.doremote(state, [[
700 coroutine = require'coroutine'; 700 coroutine = require'coroutine';
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index 0874e5bb..80b3d05c 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