diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-29 14:32:40 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-29 14:32:40 -0300 |
commit | aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f (patch) | |
tree | f11ddbfe31e2e82604e280d9ae5b026bc917429b | |
parent | 3eb1788bb4236cd983f1230ee14e2adb1b5b3ff5 (diff) | |
download | lua-aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f.tar.gz lua-aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f.tar.bz2 lua-aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f.zip |
'luaC_linkupval' moved into 'lfunc.c' code + new way to control GC speed
-rw-r--r-- | lgc.c | 136 | ||||
-rw-r--r-- | lgc.h | 24 |
2 files changed, 80 insertions, 80 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.79 2010/04/20 20:15:30 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.80 2010/04/26 17:58:00 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,16 +23,19 @@ | |||
23 | #include "ltm.h" | 23 | #include "ltm.h" |
24 | 24 | ||
25 | 25 | ||
26 | #define GCSTEPSIZE 1024u | 26 | #define GCSTEPSIZE 1024 |
27 | #define GCSWEEPMAX 40 | 27 | #define GCSWEEPMAX 40 |
28 | #define GCSWEEPCOST 10 | 28 | #define GCSWEEPCOST 1 |
29 | #define GCFINALIZECOST 100 | 29 | #define GCFINALIZECOST 50 |
30 | #define GCROOTCOST 10 | 30 | #define GCROOTCOST 10 |
31 | #define GCATOMICCOST 1000 | 31 | #define GCATOMICCOST 1000 |
32 | 32 | ||
33 | 33 | ||
34 | #define issweepphase(g) \ | 34 | /* |
35 | (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | 35 | ** standard negative debt for GC; a reasonable "time" to wait before |
36 | ** starting a new cycle | ||
37 | */ | ||
38 | #define stddebt(g) (-cast(l_mem, g->totalbytes/100) * g->gcpause) | ||
36 | 39 | ||
37 | 40 | ||
38 | /* | 41 | /* |
@@ -60,17 +63,6 @@ | |||
60 | #define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ | 63 | #define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ |
61 | reallymarkobject(g, obj2gco(t)); } | 64 | reallymarkobject(g, obj2gco(t)); } |
62 | 65 | ||
63 | |||
64 | /* | ||
65 | ** macro to tell when main invariant (white objects cannot point to black | ||
66 | ** ones) must be kept. During a non-generational collection, the sweep | ||
67 | ** phase may brak the invariant, as objects turned white may point to | ||
68 | ** still-black objects. The invariant is restored when sweep ends and | ||
69 | ** all objects are white again. During a generational collection, the | ||
70 | ** invariant must be kept all times. | ||
71 | */ | ||
72 | #define keepinvariant(g) (g->gckind == KGC_GEN || g->gcstate == GCSpropagate) | ||
73 | |||
74 | static void reallymarkobject (global_State *g, GCObject *o); | 66 | static void reallymarkobject (global_State *g, GCObject *o); |
75 | 67 | ||
76 | 68 | ||
@@ -142,9 +134,15 @@ void luaC_barrierback (lua_State *L, Table *t) { | |||
142 | global_State *g = G(L); | 134 | global_State *g = G(L); |
143 | GCObject *o = obj2gco(t); | 135 | GCObject *o = obj2gco(t); |
144 | lua_assert(isblack(o) && !isdead(g, o)); | 136 | lua_assert(isblack(o) && !isdead(g, o)); |
145 | black2gray(o); /* make table gray (again) */ | 137 | if (keepinvariant(g)) { |
146 | t->gclist = g->grayagain; | 138 | black2gray(o); /* make table gray (again) */ |
147 | g->grayagain = o; | 139 | t->gclist = g->grayagain; |
140 | g->grayagain = o; | ||
141 | } | ||
142 | else { /* sweep phase */ | ||
143 | lua_assert(issweepphase(g)); | ||
144 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ | ||
145 | } | ||
148 | } | 146 | } |
149 | 147 | ||
150 | 148 | ||
@@ -166,23 +164,6 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, | |||
166 | return o; | 164 | return o; |
167 | } | 165 | } |
168 | 166 | ||
169 | |||
170 | /* | ||
171 | ** link an upvalue back to the main root list. (It was previously in the | ||
172 | ** list of open upvalues of some thread.) | ||
173 | */ | ||
174 | void luaC_linkupval (lua_State *L, UpVal *uv) { | ||
175 | global_State *g = G(L); | ||
176 | GCObject *o = obj2gco(uv); | ||
177 | gch(o)->next = g->allgc; /* link upvalue into `allgc' list */ | ||
178 | g->allgc = o; | ||
179 | lua_assert(!isblack(o)); /* open upvalues are never black */ | ||
180 | if (isgray(o)) { /* is it marked? */ | ||
181 | gray2black(o); /* could not be black; now it can */ | ||
182 | luaC_barrier(L, uv, uv->v); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /* }====================================================== */ | 167 | /* }====================================================== */ |
187 | 168 | ||
188 | 169 | ||
@@ -287,9 +268,9 @@ static void remarkupvals (global_State *g) { | |||
287 | */ | 268 | */ |
288 | static void markroot (lua_State *L) { | 269 | static void markroot (lua_State *L) { |
289 | global_State *g = G(L); | 270 | global_State *g = G(L); |
290 | g->gray = NULL; | 271 | lua_assert(g->gckind == KGC_GEN || |
291 | g->grayagain = NULL; | 272 | (g->gray == NULL && g->grayagain == NULL && g->weak == NULL && |
292 | g->weak = g->ephemeron = g->allweak = NULL; | 273 | g->allweak == NULL && g->ephemeron == NULL)); |
293 | markobject(g, g->mainthread); | 274 | markobject(g, g->mainthread); |
294 | markvalue(g, &g->l_registry); | 275 | markvalue(g, &g->l_registry); |
295 | markmt(g); | 276 | markmt(g); |
@@ -372,7 +353,7 @@ static void traversestrongtable (global_State *g, Table *h) { | |||
372 | } | 353 | } |
373 | 354 | ||
374 | 355 | ||
375 | static void traversetable (global_State *g, Table *h) { | 356 | static int traversetable (global_State *g, Table *h) { |
376 | const TValue *mode = gfasttm(g, h->metatable, TM_MODE); | 357 | const TValue *mode = gfasttm(g, h->metatable, TM_MODE); |
377 | markobject(g, h->metatable); | 358 | markobject(g, h->metatable); |
378 | if (mode && ttisstring(mode)) { /* is there a weak mode? */ | 359 | if (mode && ttisstring(mode)) { /* is there a weak mode? */ |
@@ -380,20 +361,26 @@ static void traversetable (global_State *g, Table *h) { | |||
380 | int weakvalue = (strchr(svalue(mode), 'v') != NULL); | 361 | int weakvalue = (strchr(svalue(mode), 'v') != NULL); |
381 | if (weakkey || weakvalue) { /* is really weak? */ | 362 | if (weakkey || weakvalue) { /* is really weak? */ |
382 | black2gray(obj2gco(h)); /* keep table gray */ | 363 | black2gray(obj2gco(h)); /* keep table gray */ |
383 | if (!weakkey) /* strong keys? */ | 364 | if (!weakkey) { /* strong keys? */ |
384 | traverseweakvalue(g, h); | 365 | traverseweakvalue(g, h); |
385 | else if (!weakvalue) /* strong values? */ | 366 | return 1 + sizenode(h); |
367 | } | ||
368 | else if (!weakvalue) { /* strong values? */ | ||
386 | traverseephemeron(g, h); | 369 | traverseephemeron(g, h); |
387 | else | 370 | return 1 + h->sizearray + sizenode(h); |
371 | } | ||
372 | else { | ||
388 | linktable(h, &g->allweak); /* nothing to traverse now */ | 373 | linktable(h, &g->allweak); /* nothing to traverse now */ |
389 | return; | 374 | return 1; |
375 | } | ||
390 | } /* else go through */ | 376 | } /* else go through */ |
391 | } | 377 | } |
392 | traversestrongtable(g, h); | 378 | traversestrongtable(g, h); |
379 | return 1 + h->sizearray + (2 * sizenode(h)); | ||
393 | } | 380 | } |
394 | 381 | ||
395 | 382 | ||
396 | static void traverseproto (global_State *g, Proto *f) { | 383 | static int traverseproto (global_State *g, Proto *f) { |
397 | int i; | 384 | int i; |
398 | stringmark(f->source); | 385 | stringmark(f->source); |
399 | for (i = 0; i < f->sizek; i++) /* mark literals */ | 386 | for (i = 0; i < f->sizek; i++) /* mark literals */ |
@@ -404,6 +391,7 @@ static void traverseproto (global_State *g, Proto *f) { | |||
404 | markobject(g, f->p[i]); | 391 | markobject(g, f->p[i]); |
405 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ | 392 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ |
406 | stringmark(f->locvars[i].varname); | 393 | stringmark(f->locvars[i].varname); |
394 | return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; | ||
407 | } | 395 | } |
408 | 396 | ||
409 | 397 | ||
@@ -425,26 +413,27 @@ static l_mem traverseclosure (global_State *g, Closure *cl) { | |||
425 | } | 413 | } |
426 | 414 | ||
427 | 415 | ||
428 | static void traversestack (global_State *g, lua_State *L) { | 416 | static int traversestack (global_State *g, lua_State *L) { |
429 | StkId o; | 417 | StkId o = L->stack; |
430 | if (L->stack == NULL) | 418 | if (L->stack == NULL) |
431 | return; /* stack not completely built yet */ | 419 | return 1; /* stack not completely built yet */ |
432 | for (o = L->stack; o < L->top; o++) | 420 | for (; o < L->top; o++) |
433 | markvalue(g, o); | 421 | markvalue(g, o); |
434 | if (g->gcstate == GCSatomic) { /* final traversal? */ | 422 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
435 | StkId lim = L->stack + L->stacksize; /* real end of stack */ | 423 | StkId lim = L->stack + L->stacksize; /* real end of stack */ |
436 | for (; o < lim; o++) /* clear not-marked stack slice */ | 424 | for (; o < lim; o++) /* clear not-marked stack slice */ |
437 | setnilvalue(o); | 425 | setnilvalue(o); |
438 | } | 426 | } |
427 | return 1 + cast_int(o - L->stack); | ||
439 | } | 428 | } |
440 | 429 | ||
441 | 430 | ||
442 | /* | 431 | /* |
443 | ** traverse one gray object, turning it to black (except for threads, | 432 | ** traverse one gray object, turning it to black (except for threads, |
444 | ** which are always gray). | 433 | ** which are always gray). |
445 | ** Returns 'quantity' traversed. | 434 | ** Returns number of values traversed. |
446 | */ | 435 | */ |
447 | static l_mem propagatemark (global_State *g) { | 436 | static int propagatemark (global_State *g) { |
448 | GCObject *o = g->gray; | 437 | GCObject *o = g->gray; |
449 | lua_assert(isgray(o)); | 438 | lua_assert(isgray(o)); |
450 | gray2black(o); | 439 | gray2black(o); |
@@ -452,9 +441,7 @@ static l_mem propagatemark (global_State *g) { | |||
452 | case LUA_TTABLE: { | 441 | case LUA_TTABLE: { |
453 | Table *h = gco2t(o); | 442 | Table *h = gco2t(o); |
454 | g->gray = h->gclist; | 443 | g->gray = h->gclist; |
455 | traversetable(g, h); | 444 | return traversetable(g, h); |
456 | return sizeof(Table) + sizeof(TValue) * h->sizearray + | ||
457 | sizeof(Node) * sizenode(h); | ||
458 | } | 445 | } |
459 | case LUA_TFUNCTION: { | 446 | case LUA_TFUNCTION: { |
460 | Closure *cl = gco2cl(o); | 447 | Closure *cl = gco2cl(o); |
@@ -467,19 +454,12 @@ static l_mem propagatemark (global_State *g) { | |||
467 | th->gclist = g->grayagain; | 454 | th->gclist = g->grayagain; |
468 | g->grayagain = o; | 455 | g->grayagain = o; |
469 | black2gray(o); | 456 | black2gray(o); |
470 | traversestack(g, th); | 457 | return traversestack(g, th); |
471 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize; | ||
472 | } | 458 | } |
473 | case LUA_TPROTO: { | 459 | case LUA_TPROTO: { |
474 | Proto *p = gco2p(o); | 460 | Proto *p = gco2p(o); |
475 | g->gray = p->gclist; | 461 | g->gray = p->gclist; |
476 | traverseproto(g, p); | 462 | return traverseproto(g, p); |
477 | return sizeof(Proto) + sizeof(Instruction) * p->sizecode + | ||
478 | sizeof(Proto *) * p->sizep + | ||
479 | sizeof(TValue) * p->sizek + | ||
480 | sizeof(int) * p->sizelineinfo + | ||
481 | sizeof(LocVar) * p->sizelocvars + | ||
482 | sizeof(TString *) * p->sizeupvalues; | ||
483 | } | 463 | } |
484 | default: lua_assert(0); return 0; | 464 | default: lua_assert(0); return 0; |
485 | } | 465 | } |
@@ -673,15 +653,15 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
673 | if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ | 653 | if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ |
674 | int status; | 654 | int status; |
675 | lu_byte oldah = L->allowhook; | 655 | lu_byte oldah = L->allowhook; |
676 | lu_mem oldt = g->GCthreshold; | 656 | lu_mem oldd = g->GCdebt; |
677 | L->allowhook = 0; /* stop debug hooks during GC tag method */ | 657 | L->allowhook = 0; /* stop debug hooks during GC tag method */ |
678 | g->GCthreshold = 2 * g->totalbytes; /* avoid GC steps */ | 658 | g->GCdebt = -2 * g->totalbytes; /* avoid GC steps */ |
679 | setobj2s(L, L->top, tm); /* push finalizer... */ | 659 | setobj2s(L, L->top, tm); /* push finalizer... */ |
680 | setuvalue(L, L->top+1, udata); /* ... and its argument */ | 660 | setuvalue(L, L->top+1, udata); /* ... and its argument */ |
681 | L->top += 2; /* and (next line) call the finalizer */ | 661 | L->top += 2; /* and (next line) call the finalizer */ |
682 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); | 662 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); |
683 | L->allowhook = oldah; /* restore hooks */ | 663 | L->allowhook = oldah; /* restore hooks */ |
684 | g->GCthreshold = oldt; /* restore threshold */ | 664 | g->GCdebt = oldd; /* restore threshold */ |
685 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ | 665 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ |
686 | if (status == LUA_ERRRUN) { /* is there an error msg.? */ | 666 | if (status == LUA_ERRRUN) { /* is there an error msg.? */ |
687 | luaO_pushfstring(L, "error in __gc tag method (%s)", | 667 | luaO_pushfstring(L, "error in __gc tag method (%s)", |
@@ -791,7 +771,13 @@ static void atomic (lua_State *L) { | |||
791 | cleartable(g->weak); | 771 | cleartable(g->weak); |
792 | cleartable(g->ephemeron); | 772 | cleartable(g->ephemeron); |
793 | cleartable(g->allweak); | 773 | cleartable(g->allweak); |
774 | lua_checkmemory(L); | ||
794 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 775 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
776 | if (g->gckind != KGC_GEN) { | ||
777 | g->gray = NULL; /* all gray objects will become white */ | ||
778 | g->grayagain = NULL; | ||
779 | g->weak = g->ephemeron = g->allweak = NULL; | ||
780 | } | ||
795 | } | 781 | } |
796 | 782 | ||
797 | 783 | ||
@@ -890,23 +876,18 @@ static void generationalcollection (lua_State *L) { | |||
890 | if (g->totalbytes > g->lastmajormem/100 * g->gcpause) | 876 | if (g->totalbytes > g->lastmajormem/100 * g->gcpause) |
891 | g->lastmajormem = 0; /* signal for a major collection */ | 877 | g->lastmajormem = 0; /* signal for a major collection */ |
892 | } | 878 | } |
893 | g->GCthreshold = (g->totalbytes/100) * g->gcpause; | 879 | g->GCdebt = stddebt(g); |
894 | } | 880 | } |
895 | 881 | ||
896 | 882 | ||
897 | static void step (lua_State *L) { | 883 | static void step (lua_State *L) { |
898 | global_State *g = G(L); | 884 | global_State *g = G(L); |
899 | l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; /* how much to work */ | 885 | l_mem lim = g->gcstepmul; /* how much to work */ |
900 | lu_mem debt = g->totalbytes - g->GCthreshold; | ||
901 | lua_assert(g->gckind == KGC_NORMAL); | 886 | lua_assert(g->gckind == KGC_NORMAL); |
902 | do { /* always perform at least one single step */ | 887 | do { /* always perform at least one single step */ |
903 | lim -= singlestep(L); | 888 | lim -= singlestep(L); |
904 | } while (lim > 0 && g->gcstate != GCSpause); | 889 | } while (lim > 0 && g->gcstate != GCSpause); |
905 | g->GCthreshold = (g->gcstate != GCSpause) | 890 | g->GCdebt += (g->gcstate != GCSpause) ? -GCSTEPSIZE : stddebt(g); |
906 | ? g->totalbytes + GCSTEPSIZE | ||
907 | : (g->totalbytes/100) * g->gcpause; | ||
908 | /* compensate if GC is "behind schedule" (has some debt to pay) */ | ||
909 | if (g->GCthreshold > debt) g->GCthreshold -= debt; | ||
910 | } | 891 | } |
911 | 892 | ||
912 | 893 | ||
@@ -930,6 +911,9 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
930 | (as white has not changed, nothing will be collected) */ | 911 | (as white has not changed, nothing will be collected) */ |
931 | g->sweepstrgc = 0; | 912 | g->sweepstrgc = 0; |
932 | g->gcstate = GCSsweepstring; | 913 | g->gcstate = GCSsweepstring; |
914 | g->gray = NULL; | ||
915 | g->grayagain = NULL; | ||
916 | g->weak = g->ephemeron = g->allweak = NULL; | ||
933 | } | 917 | } |
934 | /* finish any pending sweep phase */ | 918 | /* finish any pending sweep phase */ |
935 | luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize)); | 919 | luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize)); |
@@ -943,7 +927,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
943 | g->gcstate = GCSpause; /* collector must be always in... */ | 927 | g->gcstate = GCSpause; /* collector must be always in... */ |
944 | luaC_runtilstate(L, bitmask(GCSpropagate)); /* ...propagate phase */ | 928 | luaC_runtilstate(L, bitmask(GCSpropagate)); /* ...propagate phase */ |
945 | } | 929 | } |
946 | g->GCthreshold = (g->totalbytes/100) * g->gcpause; | 930 | g->GCdebt = stddebt(g); |
947 | } | 931 | } |
948 | 932 | ||
949 | /* }====================================================== */ | 933 | /* }====================================================== */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.29 2010/03/24 15:51:10 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.30 2010/03/25 13:06:36 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,6 +23,24 @@ | |||
23 | #define GCSfinalize 6 | 23 | #define GCSfinalize 6 |
24 | 24 | ||
25 | 25 | ||
26 | #define issweepphase(g) \ | ||
27 | (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | ||
28 | |||
29 | |||
30 | /* | ||
31 | ** macro to tell when main invariant (white objects cannot point to black | ||
32 | ** ones) must be kept. During a non-generational collection, the sweep | ||
33 | ** phase may brak the invariant, as objects turned white may point to | ||
34 | ** still-black objects. The invariant is restored when sweep ends and | ||
35 | ** all objects are white again. During a generational collection, the | ||
36 | ** invariant must be kept all times. | ||
37 | */ | ||
38 | #define keepinvariant(g) (g->gckind == KGC_GEN || g->gcstate == GCSpropagate) | ||
39 | |||
40 | |||
41 | #define gcstopped(g) ((g)->GCdebt == MIN_LMEM) | ||
42 | #define stopgc(g) ((g)->GCdebt = MIN_LMEM) | ||
43 | |||
26 | 44 | ||
27 | /* | 45 | /* |
28 | ** some useful bit tricks | 46 | ** some useful bit tricks |
@@ -76,8 +94,7 @@ | |||
76 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) | 94 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) |
77 | 95 | ||
78 | 96 | ||
79 | #define luaC_checkGC(L) \ | 97 | #define luaC_checkGC(L) {condchangemem(L); if (G(L)->GCdebt > 0) luaC_step(L);} |
80 | {condchangemem(L); if (G(L)->totalbytes >= G(L)->GCthreshold) luaC_step(L);} | ||
81 | 98 | ||
82 | 99 | ||
83 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | 100 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ |
@@ -100,7 +117,6 @@ LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); | |||
100 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); | 117 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); |
101 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, | 118 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, |
102 | GCObject **list, int offset); | 119 | GCObject **list, int offset); |
103 | LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); | ||
104 | LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); | 120 | LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); |
105 | LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); | 121 | LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); |
106 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u); | 122 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u); |