Browse Source

GC parameters encoded as floating-point bytes

This encoding brings more precision and a larger range for these
parameters.
pull/33/head
Roberto Ierusalimschy 11 months ago
parent
commit
ad0ea7813b
  1. 19
      lapi.c
  2. 18
      lgc.c
  3. 20
      lgc.h
  4. 53
      lobject.c
  5. 3
      lobject.h
  6. 12
      lstate.c
  7. 12
      lstate.h
  8. 33
      ltests.c

19
lapi.c

@ -1190,12 +1190,9 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
int minormajor = va_arg(argp, int); int minormajor = va_arg(argp, int);
int majorminor = va_arg(argp, int); int majorminor = va_arg(argp, int);
res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
if (minormul >= 0) setgcparam(g, gcpgenminormul, minormul);
setgcparam(g, genminormul, minormul); setgcparam(g, gcpminormajor, minormajor);
if (minormajor >= 0) setgcparam(g, gcpmajorminor, majorminor);
setgcparam(g, minormajor, minormajor);
if (majorminor >= 0)
setgcparam(g, majorminor, majorminor);
luaC_changemode(L, KGC_GENMINOR); luaC_changemode(L, KGC_GENMINOR);
break; break;
} }
@ -1204,13 +1201,9 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
int stepmul = va_arg(argp, int); int stepmul = va_arg(argp, int);
int stepsize = va_arg(argp, int); int stepsize = va_arg(argp, int);
res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
if (pause >= 0) setgcparam(g, gcppause, pause);
setgcparam(g, gcpause, pause); setgcparam(g, gcpstepmul, stepmul);
if (stepmul >= 0) setgcparam(g, gcpstepsize, stepsize);
setgcparam(g, gcstepmul, stepmul);
if (stepsize >= 0)
g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
: log2maxs(l_obj);
luaC_changemode(L, KGC_INC); luaC_changemode(L, KGC_INC);
break; break;
} }

18
lgc.c

@ -1049,7 +1049,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
** approximately (marked * pause / 100). ** approximately (marked * pause / 100).
*/ */
static void setpause (global_State *g) { static void setpause (global_State *g) {
l_obj threshold = applygcparam(g, gcpause, g->marked); l_obj threshold = luaO_applyparam(g->gcppause, g->marked);
l_obj debt = threshold - gettotalobjs(g); l_obj debt = threshold - gettotalobjs(g);
if (debt < 0) debt = 0; if (debt < 0) debt = 0;
luaE_setdebt(g, debt); luaE_setdebt(g, debt);
@ -1233,13 +1233,13 @@ static void finishgencycle (lua_State *L, global_State *g) {
** in generational mode. ** in generational mode.
*/ */
static void minor2inc (lua_State *L, global_State *g, int kind) { static void minor2inc (lua_State *L, global_State *g, int kind) {
l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
g->GCmajorminor = g->marked; /* number of live objects */ g->GCmajorminor = g->marked; /* number of live objects */
g->gckind = kind; g->gckind = kind;
g->reallyold = g->old1 = g->survival = NULL; g->reallyold = g->old1 = g->survival = NULL;
g->finobjrold = g->finobjold1 = g->finobjsur = NULL; g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
entersweep(L); /* continue as an incremental cycle */ entersweep(L); /* continue as an incremental cycle */
luaE_setdebt(g, stepsize); /* set a debt equal to the step size */
luaE_setdebt(g, luaO_applyparam(g->gcpstepsize, 100));
} }
@ -1255,8 +1255,8 @@ static void minor2inc (lua_State *L, global_State *g, int kind) {
** major collection. (That percentage is computed in 'limit'.) ** major collection. (That percentage is computed in 'limit'.)
*/ */
static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) { static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) {
l_obj step = applygcparam(g, genminormul, g->GCmajorminor); l_obj step = luaO_applyparam(g->gcpgenminormul, g->GCmajorminor);
l_obj limit = applygcparam(g, minormajor, g->GCmajorminor); l_obj limit = luaO_applyparam(g->gcpminormajor, g->GCmajorminor);
//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g)); //printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g));
if (addedold1 >= (step >> 1) || g->marked >= limit) { if (addedold1 >= (step >> 1) || g->marked >= limit) {
minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */
@ -1347,7 +1347,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
** total number of objects grows 'genminormul'%. ** total number of objects grows 'genminormul'%.
*/ */
static void setminordebt (global_State *g) { static void setminordebt (global_State *g) {
luaE_setdebt(g, applygcparam(g, genminormul, g->GCmajorminor)); luaE_setdebt(g, luaO_applyparam(g->gcpgenminormul, g->GCmajorminor));
} }
@ -1404,7 +1404,7 @@ static int checkmajorminor (lua_State *L, global_State *g) {
if (g->gckind == KGC_GENMAJOR) { if (g->gckind == KGC_GENMAJOR) {
l_obj numobjs = gettotalobjs(g); l_obj numobjs = gettotalobjs(g);
l_obj addedobjs = numobjs - g->GCmajorminor; l_obj addedobjs = numobjs - g->GCmajorminor;
l_obj limit = applygcparam(g, majorminor, addedobjs); l_obj limit = luaO_applyparam(g->gcpmajorminor, addedobjs);
l_obj tobecollected = numobjs - g->marked; l_obj tobecollected = numobjs - g->marked;
//printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs); //printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs);
if (tobecollected > limit) { if (tobecollected > limit) {
@ -1634,8 +1634,8 @@ void luaC_runtilstate (lua_State *L, int state, int fast) {
** controls when next step will be performed. ** controls when next step will be performed.
*/ */
static void incstep (lua_State *L, global_State *g) { static void incstep (lua_State *L, global_State *g) {
l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; l_obj stepsize = luaO_applyparam(g->gcpstepsize, 100);
l_obj work2do = applygcparam(g, gcstepmul, stepsize); l_obj work2do = luaO_applyparam(g->gcpstepmul, stepsize);
int fast = 0; int fast = 0;
if (work2do == 0) { /* special case: do a full collection */ if (work2do == 0) { /* special case: do a full collection */
work2do = MAX_LOBJ; /* do unlimited work */ work2do = MAX_LOBJ; /* do unlimited work */

20
lgc.h

@ -189,10 +189,12 @@
for each new allocated object.) */ for each new allocated object.) */
#define LUAI_GCMUL 200 #define LUAI_GCMUL 200
/* How many objects to allocate before next GC step (log2) */ /* How many objects to allocate before next GC step */
#define LUAI_GCSTEPSIZE 8 /* 256 objects */ #define LUAI_GCSTEPSIZE 250
#define setgcparam(g,p,v) if ((v) >= 0) {g->p = luaO_codeparam(v);}
/* /*
** Control when GC is running: ** Control when GC is running:
*/ */
@ -201,20 +203,6 @@
#define GCSTPCLS 4 /* bit true when closing Lua state */ #define GCSTPCLS 4 /* bit true when closing Lua state */
#define gcrunning(g) ((g)->gcstp == 0) #define gcrunning(g) ((g)->gcstp == 0)
/*
** Macros to set and apply GC parameters. GC parameters are given in
** percentage points, but are stored as lu_byte. To avoid repeated
** divisions by 100, these macros store the original parameter
** multiplied by 128 and divided by 100. To apply them, if it first
** divides the value by 128 it may lose precision; if it first
** multiplies by the parameter, it may overflow. So, it first divides
** by 32, then multiply by the parameter, and then divides the result by
** 4.
*/
#define setgcparam(g,p,v) (g->gcp##p = (cast_uint(v) << 7) / 100u)
#define applygcparam(g,p,v) ((((v) >> 5) * g->gcp##p) >> 2)
/* /*
** Does one step of collection when debt becomes zero. 'pre'/'pos' ** Does one step of collection when debt becomes zero. 'pre'/'pos'

53
lobject.c

@ -33,7 +33,7 @@
** Computes ceil(log2(x)) ** Computes ceil(log2(x))
*/ */
int luaO_ceillog2 (unsigned int x) { int luaO_ceillog2 (unsigned int x) {
static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */
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, 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,
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, 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,
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, 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) {
return l + log_2[x]; return l + log_2[x];
} }
/*
** Encodes 'p'% as a floating-point byte, represented as (eeeeexxx).
** The exponent is represented using excess-7. Mimicking IEEE 754, the
** representation normalizes the number when possible, assuming an extra
** 1 before the mantissa (xxx) and adding one to the exponent (eeeeexxx)
** to signal that. So, the real value is (1xxx) * 2^(eeeee - 8) if
** eeeee != 0, and (xxx) * 2^-7 otherwise.
*/
unsigned int luaO_codeparam (unsigned int p) {
if (p >= (cast(lu_mem, 0xF) << 0xF) / 128 * 100) /* overflow? */
return 0xFF; /* return maximum value */
else {
p = (p * 128u) / 100;
if (p <= 0xF)
return p;
else {
int log = luaO_ceillog2(p + 1) - 5;
return ((p >> log) - 0x10) | ((log + 1) << 4);
}
}
}
/*
** Computes 'p' times 'x', where 'p' is a floating-point byte.
*/
l_obj luaO_applyparam (unsigned int p, l_obj x) {
unsigned int m = p & 0xF; /* mantissa */
int e = (p >> 4); /* exponent */
if (e > 0) { /* normalized? */
e--;
m += 0x10; /* maximum 'm' is 0x1F */
}
e -= 7; /* correct excess-7 */
if (e < 0) {
e = -e;
if (x < MAX_LOBJ / 0x1F) /* multiplication cannot overflow? */
return (x * m) >> e; /* multiplying first gives more precision */
else if ((x >> e) < MAX_LOBJ / 0x1F) /* cannot overflow after shift? */
return (x >> e) * m;
else /* real overflow */
return MAX_LOBJ;
}
else {
if (x < (MAX_LOBJ / 0x1F) >> e) /* no overflow? */
return (x * m) << e; /* order doesn't matter here */
else /* real overflow */
return MAX_LOBJ;
}
}
static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
lua_Integer v2) { lua_Integer v2) {

3
lobject.h

@ -826,6 +826,9 @@ typedef struct Table {
LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
LUAI_FUNC int luaO_ceillog2 (unsigned int x); LUAI_FUNC int luaO_ceillog2 (unsigned int x);
LUAI_FUNC unsigned int luaO_codeparam (unsigned int p);
LUAI_FUNC l_obj luaO_applyparam (unsigned int p, l_obj x);
LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
const TValue *p2, TValue *res); const TValue *p2, TValue *res);
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,

12
lstate.c

@ -365,12 +365,12 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
g->marked = 0; g->marked = 0;
g->GCdebt = 0; g->GCdebt = 0;
setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
setgcparam(g, gcpause, LUAI_GCPAUSE); setgcparam(g, gcppause, LUAI_GCPAUSE);
setgcparam(g, gcstepmul, LUAI_GCMUL); setgcparam(g, gcpstepmul, LUAI_GCMUL);
g->gcstepsize = LUAI_GCSTEPSIZE; setgcparam(g, gcpstepsize, LUAI_GCSTEPSIZE);
setgcparam(g, genminormul, LUAI_GENMINORMUL); setgcparam(g, gcpgenminormul, LUAI_GENMINORMUL);
setgcparam(g, minormajor, LUAI_MINORMAJOR); setgcparam(g, gcpminormajor, LUAI_MINORMAJOR);
setgcparam(g, majorminor, LUAI_MAJORMINOR); setgcparam(g, gcpmajorminor, LUAI_MAJORMINOR);
for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
/* memory allocation error: free partial state */ /* memory allocation error: free partial state */

12
lstate.h

@ -264,18 +264,18 @@ typedef struct global_State {
TValue l_registry; TValue l_registry;
TValue nilvalue; /* a nil value */ TValue nilvalue; /* a nil value */
unsigned int seed; /* randomized seed for hashes */ unsigned int seed; /* randomized seed for hashes */
unsigned short gcpgenminormul; /* control minor generational collections */ lu_byte gcpgenminormul; /* control minor generational collections */
unsigned short gcpmajorminor; /* control shift major->minor */ lu_byte gcpmajorminor; /* control shift major->minor */
unsigned short gcpminormajor; /* control shift minor->major */ lu_byte gcpminormajor; /* control shift minor->major */
unsigned short gcpgcpause; /* size of pause between successive GCs */ lu_byte gcppause; /* size of pause between successive GCs */
unsigned short gcpgcstepmul; /* GC "speed" */ lu_byte gcpstepmul; /* GC "speed" */
lu_byte gcpstepsize; /* GC granularity */
lu_byte currentwhite; lu_byte currentwhite;
lu_byte gcstate; /* state of garbage collector */ lu_byte gcstate; /* state of garbage collector */
lu_byte gckind; /* kind of GC running */ lu_byte gckind; /* kind of GC running */
lu_byte gcstopem; /* stops emergency collections */ lu_byte gcstopem; /* stops emergency collections */
lu_byte gcstp; /* control whether GC is running */ lu_byte gcstp; /* control whether GC is running */
lu_byte gcemergency; /* true if this is an emergency collection */ lu_byte gcemergency; /* true if this is an emergency collection */
lu_byte gcstepsize; /* (log2 of) GC granularity */
GCObject *allgc; /* list of all collectable objects */ GCObject *allgc; /* list of all collectable objects */
GCObject **sweepgc; /* current position of sweep in list */ GCObject **sweepgc; /* current position of sweep in list */
GCObject *finobj; /* list of collectable objects with finalizers */ GCObject *finobj; /* list of collectable objects with finalizers */

33
ltests.c

@ -1033,16 +1033,35 @@ static int table_query (lua_State *L) {
} }
static int query_inc (lua_State *L) { static int query_GCparams (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
lua_pushinteger(L, gettotalobjs(g)); lua_pushinteger(L, gettotalobjs(g));
lua_pushinteger(L, g->GCdebt); lua_pushinteger(L, g->GCdebt);
lua_pushinteger(L, applygcparam(g, gcpause, 100)); lua_pushinteger(L, luaO_applyparam(g->gcpgenminormul, 100));
lua_pushinteger(L, applygcparam(g, gcstepmul, 100)); lua_pushinteger(L, luaO_applyparam(g->gcpmajorminor, 100));
lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize); lua_pushinteger(L, luaO_applyparam(g->gcpminormajor, 100));
return 5; lua_pushinteger(L, luaO_applyparam(g->gcppause, 100));
lua_pushinteger(L, luaO_applyparam(g->gcpstepmul, 100));
lua_pushinteger(L, luaO_applyparam(g->gcpstepsize, 100));
return 8;
}
static int test_codeparam (lua_State *L) {
lua_Integer p = luaL_checkinteger(L, 1);
lua_pushinteger(L, luaO_codeparam(p));
return 1;
} }
static int test_applyparam (lua_State *L) {
lua_Integer p = luaL_checkinteger(L, 1);
lua_Integer x = luaL_checkinteger(L, 2);
lua_pushinteger(L, luaO_applyparam(p, x));
return 1;
}
static int string_query (lua_State *L) { static int string_query (lua_State *L) {
stringtable *tb = &G(L)->strt; stringtable *tb = &G(L)->strt;
int s = cast_int(luaL_optinteger(L, 1, 0)) - 1; int s = cast_int(luaL_optinteger(L, 1, 0)) - 1;
@ -1974,7 +1993,9 @@ static const struct luaL_Reg tests_funcs[] = {
{"pushuserdata", pushuserdata}, {"pushuserdata", pushuserdata},
{"querystr", string_query}, {"querystr", string_query},
{"querytab", table_query}, {"querytab", table_query},
{"queryinc", query_inc}, {"queryGCparams", query_GCparams},
{"codeparam", test_codeparam},
{"applyparam", test_applyparam},
{"ref", tref}, {"ref", tref},
{"resume", coresume}, {"resume", coresume},
{"s2d", s2d}, {"s2d", s2d},

Loading…
Cancel
Save