diff options
| -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); |
