aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-12-20 16:25:20 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-12-20 16:25:20 -0300
commitad0ea7813b39e76b377983138ca995189e22054f (patch)
tree087e3585a4b4bf5ae65f56b9599bbff9c361a123
parent666e95a66d1a2ceb98bdf320980b3f655264a9c9 (diff)
downloadlua-ad0ea7813b39e76b377983138ca995189e22054f.tar.gz
lua-ad0ea7813b39e76b377983138ca995189e22054f.tar.bz2
lua-ad0ea7813b39e76b377983138ca995189e22054f.zip
GC parameters encoded as floating-point bytes
This encoding brings more precision and a larger range for these parameters.
Diffstat (limited to '')
-rw-r--r--lapi.c19
-rw-r--r--lgc.c18
-rw-r--r--lgc.h20
-rw-r--r--lobject.c53
-rw-r--r--lobject.h3
-rw-r--r--lstate.c12
-rw-r--r--lstate.h12
-rw-r--r--ltests.c33
8 files changed, 113 insertions, 57 deletions
diff --git a/lapi.c b/lapi.c
index fd9ec4e4..3ea3d0aa 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1190,12 +1190,9 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1190 int minormajor = va_arg(argp, int); 1190 int minormajor = va_arg(argp, int);
1191 int majorminor = va_arg(argp, int); 1191 int majorminor = va_arg(argp, int);
1192 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; 1192 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1193 if (minormul >= 0) 1193 setgcparam(g, gcpgenminormul, minormul);
1194 setgcparam(g, genminormul, minormul); 1194 setgcparam(g, gcpminormajor, minormajor);
1195 if (minormajor >= 0) 1195 setgcparam(g, gcpmajorminor, majorminor);
1196 setgcparam(g, minormajor, minormajor);
1197 if (majorminor >= 0)
1198 setgcparam(g, majorminor, majorminor);
1199 luaC_changemode(L, KGC_GENMINOR); 1196 luaC_changemode(L, KGC_GENMINOR);
1200 break; 1197 break;
1201 } 1198 }
@@ -1204,13 +1201,9 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1204 int stepmul = va_arg(argp, int); 1201 int stepmul = va_arg(argp, int);
1205 int stepsize = va_arg(argp, int); 1202 int stepsize = va_arg(argp, int);
1206 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; 1203 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1207 if (pause >= 0) 1204 setgcparam(g, gcppause, pause);
1208 setgcparam(g, gcpause, pause); 1205 setgcparam(g, gcpstepmul, stepmul);
1209 if (stepmul >= 0) 1206 setgcparam(g, gcpstepsize, stepsize);
1210 setgcparam(g, gcstepmul, stepmul);
1211 if (stepsize >= 0)
1212 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
1213 : log2maxs(l_obj);
1214 luaC_changemode(L, KGC_INC); 1207 luaC_changemode(L, KGC_INC);
1215 break; 1208 break;
1216 } 1209 }
diff --git a/lgc.c b/lgc.c
index 114b32d3..149dddf6 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1049,7 +1049,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
1049** approximately (marked * pause / 100). 1049** approximately (marked * pause / 100).
1050*/ 1050*/
1051static void setpause (global_State *g) { 1051static void setpause (global_State *g) {
1052 l_obj threshold = applygcparam(g, gcpause, g->marked); 1052 l_obj threshold = luaO_applyparam(g->gcppause, g->marked);
1053 l_obj debt = threshold - gettotalobjs(g); 1053 l_obj debt = threshold - gettotalobjs(g);
1054 if (debt < 0) debt = 0; 1054 if (debt < 0) debt = 0;
1055 luaE_setdebt(g, debt); 1055 luaE_setdebt(g, debt);
@@ -1233,13 +1233,13 @@ static void finishgencycle (lua_State *L, global_State *g) {
1233** in generational mode. 1233** in generational mode.
1234*/ 1234*/
1235static void minor2inc (lua_State *L, global_State *g, int kind) { 1235static void minor2inc (lua_State *L, global_State *g, int kind) {
1236 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1237 g->GCmajorminor = g->marked; /* number of live objects */ 1236 g->GCmajorminor = g->marked; /* number of live objects */
1238 g->gckind = kind; 1237 g->gckind = kind;
1239 g->reallyold = g->old1 = g->survival = NULL; 1238 g->reallyold = g->old1 = g->survival = NULL;
1240 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1239 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1241 entersweep(L); /* continue as an incremental cycle */ 1240 entersweep(L); /* continue as an incremental cycle */
1242 luaE_setdebt(g, stepsize); 1241 /* set a debt equal to the step size */
1242 luaE_setdebt(g, luaO_applyparam(g->gcpstepsize, 100));
1243} 1243}
1244 1244
1245 1245
@@ -1255,8 +1255,8 @@ static void minor2inc (lua_State *L, global_State *g, int kind) {
1255** major collection. (That percentage is computed in 'limit'.) 1255** major collection. (That percentage is computed in 'limit'.)
1256*/ 1256*/
1257static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) { 1257static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) {
1258 l_obj step = applygcparam(g, genminormul, g->GCmajorminor); 1258 l_obj step = luaO_applyparam(g->gcpgenminormul, g->GCmajorminor);
1259 l_obj limit = applygcparam(g, minormajor, g->GCmajorminor); 1259 l_obj limit = luaO_applyparam(g->gcpminormajor, g->GCmajorminor);
1260//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g)); 1260//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g));
1261 if (addedold1 >= (step >> 1) || g->marked >= limit) { 1261 if (addedold1 >= (step >> 1) || g->marked >= limit) {
1262 minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ 1262 minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */
@@ -1347,7 +1347,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
1347** total number of objects grows 'genminormul'%. 1347** total number of objects grows 'genminormul'%.
1348*/ 1348*/
1349static void setminordebt (global_State *g) { 1349static void setminordebt (global_State *g) {
1350 luaE_setdebt(g, applygcparam(g, genminormul, g->GCmajorminor)); 1350 luaE_setdebt(g, luaO_applyparam(g->gcpgenminormul, g->GCmajorminor));
1351} 1351}
1352 1352
1353 1353
@@ -1404,7 +1404,7 @@ static int checkmajorminor (lua_State *L, global_State *g) {
1404 if (g->gckind == KGC_GENMAJOR) { 1404 if (g->gckind == KGC_GENMAJOR) {
1405 l_obj numobjs = gettotalobjs(g); 1405 l_obj numobjs = gettotalobjs(g);
1406 l_obj addedobjs = numobjs - g->GCmajorminor; 1406 l_obj addedobjs = numobjs - g->GCmajorminor;
1407 l_obj limit = applygcparam(g, majorminor, addedobjs); 1407 l_obj limit = luaO_applyparam(g->gcpmajorminor, addedobjs);
1408 l_obj tobecollected = numobjs - g->marked; 1408 l_obj tobecollected = numobjs - g->marked;
1409//printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs); 1409//printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs);
1410 if (tobecollected > limit) { 1410 if (tobecollected > limit) {
@@ -1634,8 +1634,8 @@ void luaC_runtilstate (lua_State *L, int state, int fast) {
1634** controls when next step will be performed. 1634** controls when next step will be performed.
1635*/ 1635*/
1636static void incstep (lua_State *L, global_State *g) { 1636static void incstep (lua_State *L, global_State *g) {
1637 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; 1637 l_obj stepsize = luaO_applyparam(g->gcpstepsize, 100);
1638 l_obj work2do = applygcparam(g, gcstepmul, stepsize); 1638 l_obj work2do = luaO_applyparam(g->gcpstepmul, stepsize);
1639 int fast = 0; 1639 int fast = 0;
1640 if (work2do == 0) { /* special case: do a full collection */ 1640 if (work2do == 0) { /* special case: do a full collection */
1641 work2do = MAX_LOBJ; /* do unlimited work */ 1641 work2do = MAX_LOBJ; /* do unlimited work */
diff --git a/lgc.h b/lgc.h
index e8dee8a0..6a03f787 100644
--- a/lgc.h
+++ b/lgc.h
@@ -189,10 +189,12 @@
189 for each new allocated object.) */ 189 for each new allocated object.) */
190#define LUAI_GCMUL 200 190#define LUAI_GCMUL 200
191 191
192/* How many objects to allocate before next GC step (log2) */ 192/* How many objects to allocate before next GC step */
193#define LUAI_GCSTEPSIZE 8 /* 256 objects */ 193#define LUAI_GCSTEPSIZE 250
194 194
195 195
196#define setgcparam(g,p,v) if ((v) >= 0) {g->p = luaO_codeparam(v);}
197
196/* 198/*
197** Control when GC is running: 199** Control when GC is running:
198*/ 200*/
@@ -201,20 +203,6 @@
201#define GCSTPCLS 4 /* bit true when closing Lua state */ 203#define GCSTPCLS 4 /* bit true when closing Lua state */
202#define gcrunning(g) ((g)->gcstp == 0) 204#define gcrunning(g) ((g)->gcstp == 0)
203 205
204/*
205** Macros to set and apply GC parameters. GC parameters are given in
206** percentage points, but are stored as lu_byte. To avoid repeated
207** divisions by 100, these macros store the original parameter
208** multiplied by 128 and divided by 100. To apply them, if it first
209** divides the value by 128 it may lose precision; if it first
210** multiplies by the parameter, it may overflow. So, it first divides
211** by 32, then multiply by the parameter, and then divides the result by
212** 4.
213*/
214
215#define setgcparam(g,p,v) (g->gcp##p = (cast_uint(v) << 7) / 100u)
216#define applygcparam(g,p,v) ((((v) >> 5) * g->gcp##p) >> 2)
217
218 206
219/* 207/*
220** Does one step of collection when debt becomes zero. 'pre'/'pos' 208** Does one step of collection when debt becomes zero. 'pre'/'pos'
diff --git a/lobject.c b/lobject.c
index 9cfa5227..4091b9d7 100644
--- a/lobject.c
+++ b/lobject.c
@@ -33,7 +33,7 @@
33** Computes ceil(log2(x)) 33** Computes ceil(log2(x))
34*/ 34*/
35int luaO_ceillog2 (unsigned int x) { 35int luaO_ceillog2 (unsigned int x) {
36 static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ 36 static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */
37 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 37 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
38 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 38 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
39 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 39 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
@@ -49,6 +49,57 @@ int luaO_ceillog2 (unsigned int x) {
49 return l + log_2[x]; 49 return l + log_2[x];
50} 50}
51 51
52/*
53** Encodes 'p'% as a floating-point byte, represented as (eeeeexxx).
54** The exponent is represented using excess-7. Mimicking IEEE 754, the
55** representation normalizes the number when possible, assuming an extra
56** 1 before the mantissa (xxx) and adding one to the exponent (eeeeexxx)
57** to signal that. So, the real value is (1xxx) * 2^(eeeee - 8) if
58** eeeee != 0, and (xxx) * 2^-7 otherwise.
59*/
60unsigned int luaO_codeparam (unsigned int p) {
61 if (p >= (cast(lu_mem, 0xF) << 0xF) / 128 * 100) /* overflow? */
62 return 0xFF; /* return maximum value */
63 else {
64 p = (p * 128u) / 100;
65 if (p <= 0xF)
66 return p;
67 else {
68 int log = luaO_ceillog2(p + 1) - 5;
69 return ((p >> log) - 0x10) | ((log + 1) << 4);
70 }
71 }
72}
73
74
75/*
76** Computes 'p' times 'x', where 'p' is a floating-point byte.
77*/
78l_obj luaO_applyparam (unsigned int p, l_obj x) {
79 unsigned int m = p & 0xF; /* mantissa */
80 int e = (p >> 4); /* exponent */
81 if (e > 0) { /* normalized? */
82 e--;
83 m += 0x10; /* maximum 'm' is 0x1F */
84 }
85 e -= 7; /* correct excess-7 */
86 if (e < 0) {
87 e = -e;
88 if (x < MAX_LOBJ / 0x1F) /* multiplication cannot overflow? */
89 return (x * m) >> e; /* multiplying first gives more precision */
90 else if ((x >> e) < MAX_LOBJ / 0x1F) /* cannot overflow after shift? */
91 return (x >> e) * m;
92 else /* real overflow */
93 return MAX_LOBJ;
94 }
95 else {
96 if (x < (MAX_LOBJ / 0x1F) >> e) /* no overflow? */
97 return (x * m) << e; /* order doesn't matter here */
98 else /* real overflow */
99 return MAX_LOBJ;
100 }
101}
102
52 103
53static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, 104static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
54 lua_Integer v2) { 105 lua_Integer v2) {
diff --git a/lobject.h b/lobject.h
index 6da50215..a7d85762 100644
--- a/lobject.h
+++ b/lobject.h
@@ -826,6 +826,9 @@ typedef struct Table {
826 826
827LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); 827LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
828LUAI_FUNC int luaO_ceillog2 (unsigned int x); 828LUAI_FUNC int luaO_ceillog2 (unsigned int x);
829LUAI_FUNC unsigned int luaO_codeparam (unsigned int p);
830LUAI_FUNC l_obj luaO_applyparam (unsigned int p, l_obj x);
831
829LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, 832LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
830 const TValue *p2, TValue *res); 833 const TValue *p2, TValue *res);
831LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, 834LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
diff --git a/lstate.c b/lstate.c
index aab90e34..19505845 100644
--- a/lstate.c
+++ b/lstate.c
@@ -365,12 +365,12 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
365 g->marked = 0; 365 g->marked = 0;
366 g->GCdebt = 0; 366 g->GCdebt = 0;
367 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ 367 setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
368 setgcparam(g, gcpause, LUAI_GCPAUSE); 368 setgcparam(g, gcppause, LUAI_GCPAUSE);
369 setgcparam(g, gcstepmul, LUAI_GCMUL); 369 setgcparam(g, gcpstepmul, LUAI_GCMUL);
370 g->gcstepsize = LUAI_GCSTEPSIZE; 370 setgcparam(g, gcpstepsize, LUAI_GCSTEPSIZE);
371 setgcparam(g, genminormul, LUAI_GENMINORMUL); 371 setgcparam(g, gcpgenminormul, LUAI_GENMINORMUL);
372 setgcparam(g, minormajor, LUAI_MINORMAJOR); 372 setgcparam(g, gcpminormajor, LUAI_MINORMAJOR);
373 setgcparam(g, majorminor, LUAI_MAJORMINOR); 373 setgcparam(g, gcpmajorminor, LUAI_MAJORMINOR);
374 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 374 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
375 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 375 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
376 /* memory allocation error: free partial state */ 376 /* memory allocation error: free partial state */
diff --git a/lstate.h b/lstate.h
index 49acfb7e..5e2020e7 100644
--- a/lstate.h
+++ b/lstate.h
@@ -264,18 +264,18 @@ typedef struct global_State {
264 TValue l_registry; 264 TValue l_registry;
265 TValue nilvalue; /* a nil value */ 265 TValue nilvalue; /* a nil value */
266 unsigned int seed; /* randomized seed for hashes */ 266 unsigned int seed; /* randomized seed for hashes */
267 unsigned short gcpgenminormul; /* control minor generational collections */ 267 lu_byte gcpgenminormul; /* control minor generational collections */
268 unsigned short gcpmajorminor; /* control shift major->minor */ 268 lu_byte gcpmajorminor; /* control shift major->minor */
269 unsigned short gcpminormajor; /* control shift minor->major */ 269 lu_byte gcpminormajor; /* control shift minor->major */
270 unsigned short gcpgcpause; /* size of pause between successive GCs */ 270 lu_byte gcppause; /* size of pause between successive GCs */
271 unsigned short gcpgcstepmul; /* GC "speed" */ 271 lu_byte gcpstepmul; /* GC "speed" */
272 lu_byte gcpstepsize; /* GC granularity */
272 lu_byte currentwhite; 273 lu_byte currentwhite;
273 lu_byte gcstate; /* state of garbage collector */ 274 lu_byte gcstate; /* state of garbage collector */
274 lu_byte gckind; /* kind of GC running */ 275 lu_byte gckind; /* kind of GC running */
275 lu_byte gcstopem; /* stops emergency collections */ 276 lu_byte gcstopem; /* stops emergency collections */
276 lu_byte gcstp; /* control whether GC is running */ 277 lu_byte gcstp; /* control whether GC is running */
277 lu_byte gcemergency; /* true if this is an emergency collection */ 278 lu_byte gcemergency; /* true if this is an emergency collection */
278 lu_byte gcstepsize; /* (log2 of) GC granularity */
279 GCObject *allgc; /* list of all collectable objects */ 279 GCObject *allgc; /* list of all collectable objects */
280 GCObject **sweepgc; /* current position of sweep in list */ 280 GCObject **sweepgc; /* current position of sweep in list */
281 GCObject *finobj; /* list of collectable objects with finalizers */ 281 GCObject *finobj; /* list of collectable objects with finalizers */
diff --git a/ltests.c b/ltests.c
index 51e4ff9b..93af528e 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1033,16 +1033,35 @@ static int table_query (lua_State *L) {
1033} 1033}
1034 1034
1035 1035
1036static int query_inc (lua_State *L) { 1036static int query_GCparams (lua_State *L) {
1037 global_State *g = G(L); 1037 global_State *g = G(L);
1038 lua_pushinteger(L, gettotalobjs(g)); 1038 lua_pushinteger(L, gettotalobjs(g));
1039 lua_pushinteger(L, g->GCdebt); 1039 lua_pushinteger(L, g->GCdebt);
1040 lua_pushinteger(L, applygcparam(g, gcpause, 100)); 1040 lua_pushinteger(L, luaO_applyparam(g->gcpgenminormul, 100));
1041 lua_pushinteger(L, applygcparam(g, gcstepmul, 100)); 1041 lua_pushinteger(L, luaO_applyparam(g->gcpmajorminor, 100));
1042 lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize); 1042 lua_pushinteger(L, luaO_applyparam(g->gcpminormajor, 100));
1043 return 5; 1043 lua_pushinteger(L, luaO_applyparam(g->gcppause, 100));
1044 lua_pushinteger(L, luaO_applyparam(g->gcpstepmul, 100));
1045 lua_pushinteger(L, luaO_applyparam(g->gcpstepsize, 100));
1046 return 8;
1047}
1048
1049
1050static int test_codeparam (lua_State *L) {
1051 lua_Integer p = luaL_checkinteger(L, 1);
1052 lua_pushinteger(L, luaO_codeparam(p));
1053 return 1;
1044} 1054}
1045 1055
1056
1057static int test_applyparam (lua_State *L) {
1058 lua_Integer p = luaL_checkinteger(L, 1);
1059 lua_Integer x = luaL_checkinteger(L, 2);
1060 lua_pushinteger(L, luaO_applyparam(p, x));
1061 return 1;
1062}
1063
1064
1046static int string_query (lua_State *L) { 1065static int string_query (lua_State *L) {
1047 stringtable *tb = &G(L)->strt; 1066 stringtable *tb = &G(L)->strt;
1048 int s = cast_int(luaL_optinteger(L, 1, 0)) - 1; 1067 int s = cast_int(luaL_optinteger(L, 1, 0)) - 1;
@@ -1974,7 +1993,9 @@ static const struct luaL_Reg tests_funcs[] = {
1974 {"pushuserdata", pushuserdata}, 1993 {"pushuserdata", pushuserdata},
1975 {"querystr", string_query}, 1994 {"querystr", string_query},
1976 {"querytab", table_query}, 1995 {"querytab", table_query},
1977 {"queryinc", query_inc}, 1996 {"queryGCparams", query_GCparams},
1997 {"codeparam", test_codeparam},
1998 {"applyparam", test_applyparam},
1978 {"ref", tref}, 1999 {"ref", tref},
1979 {"resume", coresume}, 2000 {"resume", coresume},
1980 {"s2d", s2d}, 2001 {"s2d", s2d},