GC parameters encoded as floating-point bytes
This encoding brings more precision and a larger range for these parameters.
This commit is contained in:
19
lapi.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
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
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
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) {
|
||||||
|
|||||||
@@ -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
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
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
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},
|
||||||
|
|||||||
Reference in New Issue
Block a user