aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2022-12-13 11:55:14 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2022-12-13 11:55:14 -0300
commit40565b4a089f44fdcb16f4ed0080b0ca3755e4aa (patch)
treed3d692070a250e5756fad95388606736253da8c4
parentff106c028ca944ee5e95b005628e2669b87bcaf2 (diff)
downloadlua-40565b4a089f44fdcb16f4ed0080b0ca3755e4aa.tar.gz
lua-40565b4a089f44fdcb16f4ed0080b0ca3755e4aa.tar.bz2
lua-40565b4a089f44fdcb16f4ed0080b0ca3755e4aa.zip
Revamp of GC parameters
More uniformity when handling GC parameters + avoid divisions by 100 when applying them.
Diffstat (limited to '')
-rw-r--r--lapi.c30
-rw-r--r--lgc.c14
-rw-r--r--lgc.h44
-rw-r--r--llimits.h2
-rw-r--r--lstate.c8
-rw-r--r--ltests.c4
6 files changed, 61 insertions, 41 deletions
diff --git a/lapi.c b/lapi.c
index d6d7a8db..8c70bd4c 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1185,15 +1185,15 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1185 break; 1185 break;
1186 } 1186 }
1187 case LUA_GCSETPAUSE: { 1187 case LUA_GCSETPAUSE: {
1188 int data = va_arg(argp, int); 1188 unsigned int data = va_arg(argp, unsigned int);
1189 res = getgcparam(g->gcpause); 1189 res = applygcparam(g, gcpause, 100);
1190 setgcparam(g->gcpause, data); 1190 setgcparam(g, gcpause, data);
1191 break; 1191 break;
1192 } 1192 }
1193 case LUA_GCSETSTEPMUL: { 1193 case LUA_GCSETSTEPMUL: {
1194 int data = va_arg(argp, int); 1194 unsigned int data = va_arg(argp, unsigned int);
1195 res = getgcparam(g->gcstepmul); 1195 res = applygcparam(g, gcstepmul, 100);
1196 setgcparam(g->gcstepmul, data); 1196 setgcparam(g, gcstepmul, data);
1197 break; 1197 break;
1198 } 1198 }
1199 case LUA_GCISRUNNING: { 1199 case LUA_GCISRUNNING: {
@@ -1201,25 +1201,25 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1201 break; 1201 break;
1202 } 1202 }
1203 case LUA_GCGEN: { 1203 case LUA_GCGEN: {
1204 int minormul = va_arg(argp, int); 1204 unsigned int minormul = va_arg(argp, unsigned int);
1205 int majormul = va_arg(argp, int); 1205 unsigned int majormul = va_arg(argp, unsigned int);
1206 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; 1206 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1207 if (minormul != 0) 1207 if (minormul != 0)
1208 g->genminormul = minormul; 1208 setgcparam(g, genminormul, minormul);
1209 if (majormul != 0) 1209 if (majormul != 0)
1210 setgcparam(g->genmajormul, majormul); 1210 setgcparam(g, genmajormul, majormul);
1211 luaC_changemode(L, KGC_GEN); 1211 luaC_changemode(L, KGC_GEN);
1212 break; 1212 break;
1213 } 1213 }
1214 case LUA_GCINC: { 1214 case LUA_GCINC: {
1215 int pause = va_arg(argp, int); 1215 unsigned int pause = va_arg(argp, unsigned int);
1216 int stepmul = va_arg(argp, int); 1216 unsigned int stepmul = va_arg(argp, unsigned int);
1217 int stepsize = va_arg(argp, int); 1217 unsigned int stepsize = va_arg(argp, unsigned int);
1218 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; 1218 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1219 if (pause != 0) 1219 if (pause != 0)
1220 setgcparam(g->gcpause, pause); 1220 setgcparam(g, gcpause, pause);
1221 if (stepmul != 0) 1221 if (stepmul != 0)
1222 setgcparam(g->gcstepmul, stepmul); 1222 setgcparam(g, gcstepmul, stepmul);
1223 if (stepsize != 0) 1223 if (stepsize != 0)
1224 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize 1224 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
1225 : log2maxs(l_obj); 1225 : log2maxs(l_obj);
diff --git a/lgc.c b/lgc.c
index c2b0535d..90a49091 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1030,14 +1030,10 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
1030/* 1030/*
1031** 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
1032** start when number of objects in use hits the threshold of 1032** start when number of objects in use hits the threshold of
1033** approximately ('marked' * pause / 100). (A direct multiplication 1033** approximately (marked * pause / 100).
1034** by 'pause' may overflow, and a direct division by 100 may undeflow
1035** to zero. So, the division is done in two steps. 8 * 12 is near 100
1036** and the division by 8 is cheap.)
1037*/ 1034*/
1038static void setpause (global_State *g) { 1035static void setpause (global_State *g) {
1039 unsigned int pause = getgcparam(g->gcpause); 1036 l_obj threshold = applygcparam(g, gcpause, g->marked);
1040 l_obj threshold = g->marked / 8 * pause / 12;
1041 l_obj debt = gettotalobjs(g) - threshold; 1037 l_obj debt = gettotalobjs(g) - threshold;
1042 if (debt > 0) debt = 0; 1038 if (debt > 0) debt = 0;
1043 luaE_setdebt(g, debt); 1039 luaE_setdebt(g, debt);
@@ -1289,7 +1285,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
1289** total number of objects grows 'genminormul'%. 1285** total number of objects grows 'genminormul'%.
1290*/ 1286*/
1291static void setminordebt (global_State *g) { 1287static void setminordebt (global_State *g) {
1292 luaE_setdebt(g, -(gettotalobjs(g) / 100) * g->genminormul); 1288 luaE_setdebt(g, -applygcparam(g, genminormul, gettotalobjs(g)));
1293} 1289}
1294 1290
1295 1291
@@ -1387,7 +1383,7 @@ static void genmajorstep (lua_State *L, global_State *g) {
1387*/ 1383*/
1388static void genstep (lua_State *L, global_State *g) { 1384static void genstep (lua_State *L, global_State *g) {
1389 l_obj majorbase = g->GClastmajor; /* count after last major collection */ 1385 l_obj majorbase = g->GClastmajor; /* count after last major collection */
1390 l_obj majorinc = (majorbase / 100) * getgcparam(g->genmajormul); 1386 l_obj majorinc = applygcparam(g, genmajormul, majorbase);
1391 if (g->GCdebt > 0 && gettotalobjs(g) > majorbase + majorinc) { 1387 if (g->GCdebt > 0 && gettotalobjs(g) > majorbase + majorinc) {
1392 /* do a major collection */ 1388 /* do a major collection */
1393 enterinc(g); 1389 enterinc(g);
@@ -1601,7 +1597,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1601*/ 1597*/
1602static void incstep (lua_State *L, global_State *g) { 1598static void incstep (lua_State *L, global_State *g) {
1603 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; 1599 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1604 l_obj work2do = stepsize * getgcparam(g->gcstepmul) / 100; 1600 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1605 do { /* repeat until pause or enough "credit" (negative debt) */ 1601 do { /* repeat until pause or enough "credit" (negative debt) */
1606 l_obj work = singlestep(L); /* perform one single step */ 1602 l_obj work = singlestep(L); /* perform one single step */
1607 work2do -= work; 1603 work2do -= work;
diff --git a/lgc.h b/lgc.h
index 3c871969..6d82690d 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,20 +125,18 @@
122 125
123 126
124/* Default Values for GC parameters */ 127/* Default Values for GC parameters */
125#define LUAI_GENMAJORMUL 100 128
126#define LUAI_GENMINORMUL 20 129/* generational */
130
131#define LUAI_GENMAJORMUL 100 /* major multiplier */
132#define LUAI_GENMINORMUL 20 /* minor multiplier */
133
134/* incremental */
127 135
128/* wait memory to double before starting new cycle */ 136/* wait memory to double before starting new cycle */
129#define LUAI_GCPAUSE 200 137#define LUAI_GCPAUSE 200
130 138
131/* 139#define LUAI_GCMUL 300 /* step multiplier */
132** some gc parameters are stored divided by 4 to allow a maximum value
133** up to 1023 in a 'lu_byte'.
134*/
135#define getgcparam(p) ((p) * 4)
136#define setgcparam(p,v) ((p) = (v) / 4)
137
138#define LUAI_GCMUL 300
139 140
140/* how many objects to allocate before next GC step (log2) */ 141/* how many objects to allocate before next GC step (log2) */
141#define LUAI_GCSTEPSIZE 8 /* 256 objects */ 142#define LUAI_GCSTEPSIZE 8 /* 256 objects */
@@ -149,6 +150,29 @@
149#define GCSTPCLS 4 /* bit true when closing Lua state */ 150#define GCSTPCLS 4 /* bit true when closing Lua state */
150#define gcrunning(g) ((g)->gcstp == 0) 151#define gcrunning(g) ((g)->gcstp == 0)
151 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
152 176
153/* 177/*
154** Does one step of collection when debt becomes positive. 'pre'/'pos' 178** Does one step of collection when debt becomes positive. 'pre'/'pos'
diff --git a/llimits.h b/llimits.h
index 525b3647..e4948791 100644
--- a/llimits.h
+++ b/llimits.h
@@ -18,7 +18,7 @@
18/* 18/*
19** 'lu_mem' is an unsigned integer big enough to count the total memory 19** 'lu_mem' is an unsigned integer big enough to count the total memory
20** used by Lua (in bytes). 'l_obj' is a signed integer big enough to 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 negative due 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 22** to the use of debt in several computations.) Usually, 'size_t' and
23** '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.
24*/ 24*/
diff --git a/lstate.c b/lstate.c
index a4379f93..b9897d96 100644
--- a/lstate.c
+++ b/lstate.c
@@ -392,11 +392,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
392 g->marked = 0; 392 g->marked = 0;
393 g->GCdebt = 0; 393 g->GCdebt = 0;
394 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 */
395 setgcparam(g->gcpause, LUAI_GCPAUSE); 395 setgcparam(g, gcpause, LUAI_GCPAUSE);
396 setgcparam(g->gcstepmul, LUAI_GCMUL); 396 setgcparam(g, gcstepmul, LUAI_GCMUL);
397 g->gcstepsize = LUAI_GCSTEPSIZE; 397 g->gcstepsize = LUAI_GCSTEPSIZE;
398 setgcparam(g->genmajormul, LUAI_GENMAJORMUL); 398 setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
399 g->genminormul = LUAI_GENMINORMUL; 399 setgcparam(g, genminormul, LUAI_GENMINORMUL);
400 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 400 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
401 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 401 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
402 /* memory allocation error: free partial state */ 402 /* memory allocation error: free partial state */
diff --git a/ltests.c b/ltests.c
index d5d2ae68..e2e0d983 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1031,8 +1031,8 @@ static int query_inc (lua_State *L) {
1031 global_State *g = G(L); 1031 global_State *g = G(L);
1032 lua_pushinteger(L, gettotalobjs(g)); 1032 lua_pushinteger(L, gettotalobjs(g));
1033 lua_pushinteger(L, g->GCdebt); 1033 lua_pushinteger(L, g->GCdebt);
1034 lua_pushinteger(L, getgcparam(g->gcpause)); 1034 lua_pushinteger(L, applygcparam(g, gcpause, 100));
1035 lua_pushinteger(L, getgcparam(g->gcstepmul)); 1035 lua_pushinteger(L, applygcparam(g, gcstepmul, 100));
1036 lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize); 1036 lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize);
1037 return 5; 1037 return 5;
1038} 1038}