diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-20 16:25:20 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-20 16:25:20 -0300 |
commit | ad0ea7813b39e76b377983138ca995189e22054f (patch) | |
tree | 087e3585a4b4bf5ae65f56b9599bbff9c361a123 | |
parent | 666e95a66d1a2ceb98bdf320980b3f655264a9c9 (diff) | |
download | lua-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.c | 19 | ||||
-rw-r--r-- | lgc.c | 18 | ||||
-rw-r--r-- | lgc.h | 20 | ||||
-rw-r--r-- | lobject.c | 53 | ||||
-rw-r--r-- | lobject.h | 3 | ||||
-rw-r--r-- | lstate.c | 12 | ||||
-rw-r--r-- | lstate.h | 12 | ||||
-rw-r--r-- | ltests.c | 33 |
8 files changed, 113 insertions, 57 deletions
@@ -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 | } |
@@ -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 | */ |
1051 | static void setpause (global_State *g) { | 1051 | static 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 | */ |
1235 | static void minor2inc (lua_State *L, global_State *g, int kind) { | 1235 | static 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 | */ |
1257 | static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) { | 1257 | static 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 | */ |
1349 | static void setminordebt (global_State *g) { | 1349 | static 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 | */ |
1636 | static void incstep (lua_State *L, global_State *g) { | 1636 | static 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 */ |
@@ -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' |
@@ -33,7 +33,7 @@ | |||
33 | ** Computes ceil(log2(x)) | 33 | ** Computes ceil(log2(x)) |
34 | */ | 34 | */ |
35 | int luaO_ceillog2 (unsigned int x) { | 35 | int 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 | */ | ||
60 | unsigned 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 | */ | ||
78 | l_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 | ||
53 | static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, | 104 | static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, |
54 | lua_Integer v2) { | 105 | lua_Integer v2) { |
@@ -826,6 +826,9 @@ typedef struct Table { | |||
826 | 826 | ||
827 | LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); | 827 | LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); |
828 | LUAI_FUNC int luaO_ceillog2 (unsigned int x); | 828 | LUAI_FUNC int luaO_ceillog2 (unsigned int x); |
829 | LUAI_FUNC unsigned int luaO_codeparam (unsigned int p); | ||
830 | LUAI_FUNC l_obj luaO_applyparam (unsigned int p, l_obj x); | ||
831 | |||
829 | LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, | 832 | LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, |
830 | const TValue *p2, TValue *res); | 833 | const TValue *p2, TValue *res); |
831 | LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, | 834 | LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, |
@@ -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 */ |
@@ -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 */ |
@@ -1033,16 +1033,35 @@ static int table_query (lua_State *L) { | |||
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | 1035 | ||
1036 | static int query_inc (lua_State *L) { | 1036 | static 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 | |||
1050 | static 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 | |||
1057 | static 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 | |||
1046 | static int string_query (lua_State *L) { | 1065 | static 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}, |