summaryrefslogtreecommitdiff
path: root/src/lj_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_gc.c')
-rw-r--r--src/lj_gc.c193
1 files changed, 126 insertions, 67 deletions
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 06484f6f..c3a0c258 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -12,6 +12,7 @@
12#include "lj_obj.h" 12#include "lj_obj.h"
13#include "lj_gc.h" 13#include "lj_gc.h"
14#include "lj_err.h" 14#include "lj_err.h"
15#include "lj_buf.h"
15#include "lj_str.h" 16#include "lj_str.h"
16#include "lj_tab.h" 17#include "lj_tab.h"
17#include "lj_func.h" 18#include "lj_func.h"
@@ -24,7 +25,9 @@
24#include "lj_cdata.h" 25#include "lj_cdata.h"
25#endif 26#endif
26#include "lj_trace.h" 27#include "lj_trace.h"
28#include "lj_dispatch.h"
27#include "lj_vm.h" 29#include "lj_vm.h"
30#include "lj_vmevent.h"
28 31
29#define GCSTEPSIZE 1024u 32#define GCSTEPSIZE 1024u
30#define GCSWEEPMAX 40 33#define GCSWEEPMAX 40
@@ -40,7 +43,8 @@
40 43
41/* Mark a TValue (if needed). */ 44/* Mark a TValue (if needed). */
42#define gc_marktv(g, tv) \ 45#define gc_marktv(g, tv) \
43 { lua_assert(!tvisgcv(tv) || (~itype(tv) == gcval(tv)->gch.gct)); \ 46 { lj_assertG(!tvisgcv(tv) || (~itype(tv) == gcval(tv)->gch.gct), \
47 "TValue and GC type mismatch"); \
44 if (tviswhite(tv)) gc_mark(g, gcV(tv)); } 48 if (tviswhite(tv)) gc_mark(g, gcV(tv)); }
45 49
46/* Mark a GCobj (if needed). */ 50/* Mark a GCobj (if needed). */
@@ -54,21 +58,32 @@
54static void gc_mark(global_State *g, GCobj *o) 58static void gc_mark(global_State *g, GCobj *o)
55{ 59{
56 int gct = o->gch.gct; 60 int gct = o->gch.gct;
57 lua_assert(iswhite(o) && !isdead(g, o)); 61 lj_assertG(iswhite(o), "mark of non-white object");
62 lj_assertG(!isdead(g, o), "mark of dead object");
58 white2gray(o); 63 white2gray(o);
59 if (LJ_UNLIKELY(gct == ~LJ_TUDATA)) { 64 if (LJ_UNLIKELY(gct == ~LJ_TUDATA)) {
60 GCtab *mt = tabref(gco2ud(o)->metatable); 65 GCtab *mt = tabref(gco2ud(o)->metatable);
61 gray2black(o); /* Userdata are never gray. */ 66 gray2black(o); /* Userdata are never gray. */
62 if (mt) gc_markobj(g, mt); 67 if (mt) gc_markobj(g, mt);
63 gc_markobj(g, tabref(gco2ud(o)->env)); 68 gc_markobj(g, tabref(gco2ud(o)->env));
69 if (LJ_HASBUFFER && gco2ud(o)->udtype == UDTYPE_BUFFER) {
70 SBufExt *sbx = (SBufExt *)uddata(gco2ud(o));
71 if (sbufiscow(sbx) && gcref(sbx->cowref))
72 gc_markobj(g, gcref(sbx->cowref));
73 if (gcref(sbx->dict_str))
74 gc_markobj(g, gcref(sbx->dict_str));
75 if (gcref(sbx->dict_mt))
76 gc_markobj(g, gcref(sbx->dict_mt));
77 }
64 } else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) { 78 } else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) {
65 GCupval *uv = gco2uv(o); 79 GCupval *uv = gco2uv(o);
66 gc_marktv(g, uvval(uv)); 80 gc_marktv(g, uvval(uv));
67 if (uv->closed) 81 if (uv->closed)
68 gray2black(o); /* Closed upvalues are never gray. */ 82 gray2black(o); /* Closed upvalues are never gray. */
69 } else if (gct != ~LJ_TSTR && gct != ~LJ_TCDATA) { 83 } else if (gct != ~LJ_TSTR && gct != ~LJ_TCDATA) {
70 lua_assert(gct == ~LJ_TFUNC || gct == ~LJ_TTAB || 84 lj_assertG(gct == ~LJ_TFUNC || gct == ~LJ_TTAB ||
71 gct == ~LJ_TTHREAD || gct == ~LJ_TPROTO); 85 gct == ~LJ_TTHREAD || gct == ~LJ_TPROTO || gct == ~LJ_TTRACE,
86 "bad GC type %d", gct);
72 setgcrefr(o->gch.gclist, g->gc.gray); 87 setgcrefr(o->gch.gclist, g->gc.gray);
73 setgcref(g->gc.gray, o); 88 setgcref(g->gc.gray, o);
74 } 89 }
@@ -101,7 +116,8 @@ static void gc_mark_uv(global_State *g)
101{ 116{
102 GCupval *uv; 117 GCupval *uv;
103 for (uv = uvnext(&g->uvhead); uv != &g->uvhead; uv = uvnext(uv)) { 118 for (uv = uvnext(&g->uvhead); uv != &g->uvhead; uv = uvnext(uv)) {
104 lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv); 119 lj_assertG(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv,
120 "broken upvalue chain");
105 if (isgray(obj2gco(uv))) 121 if (isgray(obj2gco(uv)))
106 gc_marktv(g, uvval(uv)); 122 gc_marktv(g, uvval(uv));
107 } 123 }
@@ -196,7 +212,7 @@ static int gc_traverse_tab(global_State *g, GCtab *t)
196 for (i = 0; i <= hmask; i++) { 212 for (i = 0; i <= hmask; i++) {
197 Node *n = &node[i]; 213 Node *n = &node[i];
198 if (!tvisnil(&n->val)) { /* Mark non-empty slot. */ 214 if (!tvisnil(&n->val)) { /* Mark non-empty slot. */
199 lua_assert(!tvisnil(&n->key)); 215 lj_assertG(!tvisnil(&n->key), "mark of nil key in non-empty slot");
200 if (!(weak & LJ_GC_WEAKKEY)) gc_marktv(g, &n->key); 216 if (!(weak & LJ_GC_WEAKKEY)) gc_marktv(g, &n->key);
201 if (!(weak & LJ_GC_WEAKVAL)) gc_marktv(g, &n->val); 217 if (!(weak & LJ_GC_WEAKVAL)) gc_marktv(g, &n->val);
202 } 218 }
@@ -211,7 +227,8 @@ static void gc_traverse_func(global_State *g, GCfunc *fn)
211 gc_markobj(g, tabref(fn->c.env)); 227 gc_markobj(g, tabref(fn->c.env));
212 if (isluafunc(fn)) { 228 if (isluafunc(fn)) {
213 uint32_t i; 229 uint32_t i;
214 lua_assert(fn->l.nupvalues <= funcproto(fn)->sizeuv); 230 lj_assertG(fn->l.nupvalues <= funcproto(fn)->sizeuv,
231 "function upvalues out of range");
215 gc_markobj(g, funcproto(fn)); 232 gc_markobj(g, funcproto(fn));
216 for (i = 0; i < fn->l.nupvalues; i++) /* Mark Lua function upvalues. */ 233 for (i = 0; i < fn->l.nupvalues; i++) /* Mark Lua function upvalues. */
217 gc_markobj(g, &gcref(fn->l.uvptr[i])->uv); 234 gc_markobj(g, &gcref(fn->l.uvptr[i])->uv);
@@ -227,7 +244,7 @@ static void gc_traverse_func(global_State *g, GCfunc *fn)
227static void gc_marktrace(global_State *g, TraceNo traceno) 244static void gc_marktrace(global_State *g, TraceNo traceno)
228{ 245{
229 GCobj *o = obj2gco(traceref(G2J(g), traceno)); 246 GCobj *o = obj2gco(traceref(G2J(g), traceno));
230 lua_assert(traceno != G2J(g)->cur.traceno); 247 lj_assertG(traceno != G2J(g)->cur.traceno, "active trace escaped");
231 if (iswhite(o)) { 248 if (iswhite(o)) {
232 white2gray(o); 249 white2gray(o);
233 setgcrefr(o->gch.gclist, g->gc.gray); 250 setgcrefr(o->gch.gclist, g->gc.gray);
@@ -244,6 +261,8 @@ static void gc_traverse_trace(global_State *g, GCtrace *T)
244 IRIns *ir = &T->ir[ref]; 261 IRIns *ir = &T->ir[ref];
245 if (ir->o == IR_KGC) 262 if (ir->o == IR_KGC)
246 gc_markobj(g, ir_kgc(ir)); 263 gc_markobj(g, ir_kgc(ir));
264 if (irt_is64(ir->t) && ir->o != IR_KNULL)
265 ref++;
247 } 266 }
248 if (T->link) gc_marktrace(g, T->link); 267 if (T->link) gc_marktrace(g, T->link);
249 if (T->nextroot) gc_marktrace(g, T->nextroot); 268 if (T->nextroot) gc_marktrace(g, T->nextroot);
@@ -274,12 +293,12 @@ static MSize gc_traverse_frames(global_State *g, lua_State *th)
274{ 293{
275 TValue *frame, *top = th->top-1, *bot = tvref(th->stack); 294 TValue *frame, *top = th->top-1, *bot = tvref(th->stack);
276 /* Note: extra vararg frame not skipped, marks function twice (harmless). */ 295 /* Note: extra vararg frame not skipped, marks function twice (harmless). */
277 for (frame = th->base-1; frame > bot; frame = frame_prev(frame)) { 296 for (frame = th->base-1; frame > bot+LJ_FR2; frame = frame_prev(frame)) {
278 GCfunc *fn = frame_func(frame); 297 GCfunc *fn = frame_func(frame);
279 TValue *ftop = frame; 298 TValue *ftop = frame;
280 if (isluafunc(fn)) ftop += funcproto(fn)->framesize; 299 if (isluafunc(fn)) ftop += funcproto(fn)->framesize;
281 if (ftop > top) top = ftop; 300 if (ftop > top) top = ftop;
282 gc_markobj(g, fn); /* Need to mark hidden function (or L). */ 301 if (!LJ_FR2) gc_markobj(g, fn); /* Need to mark hidden function (or L). */
283 } 302 }
284 top++; /* Correct bias of -1 (frame == base-1). */ 303 top++; /* Correct bias of -1 (frame == base-1). */
285 if (top > tvref(th->maxstack)) top = tvref(th->maxstack); 304 if (top > tvref(th->maxstack)) top = tvref(th->maxstack);
@@ -290,7 +309,7 @@ static MSize gc_traverse_frames(global_State *g, lua_State *th)
290static void gc_traverse_thread(global_State *g, lua_State *th) 309static void gc_traverse_thread(global_State *g, lua_State *th)
291{ 310{
292 TValue *o, *top = th->top; 311 TValue *o, *top = th->top;
293 for (o = tvref(th->stack)+1; o < top; o++) 312 for (o = tvref(th->stack)+1+LJ_FR2; o < top; o++)
294 gc_marktv(g, o); 313 gc_marktv(g, o);
295 if (g->gc.state == GCSatomic) { 314 if (g->gc.state == GCSatomic) {
296 top = tvref(th->stack) + th->stacksize; 315 top = tvref(th->stack) + th->stacksize;
@@ -306,7 +325,7 @@ static size_t propagatemark(global_State *g)
306{ 325{
307 GCobj *o = gcref(g->gc.gray); 326 GCobj *o = gcref(g->gc.gray);
308 int gct = o->gch.gct; 327 int gct = o->gch.gct;
309 lua_assert(isgray(o)); 328 lj_assertG(isgray(o), "propagation of non-gray object");
310 gray2black(o); 329 gray2black(o);
311 setgcrefr(g->gc.gray, o->gch.gclist); /* Remove from gray list. */ 330 setgcrefr(g->gc.gray, o->gch.gclist); /* Remove from gray list. */
312 if (LJ_LIKELY(gct == ~LJ_TTAB)) { 331 if (LJ_LIKELY(gct == ~LJ_TTAB)) {
@@ -338,7 +357,7 @@ static size_t propagatemark(global_State *g)
338 return ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) + 357 return ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
339 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry); 358 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry);
340#else 359#else
341 lua_assert(0); 360 lj_assertG(0, "bad GC type %d", gct);
342 return 0; 361 return 0;
343#endif 362#endif
344 } 363 }
@@ -355,15 +374,6 @@ static size_t gc_propagate_gray(global_State *g)
355 374
356/* -- Sweep phase --------------------------------------------------------- */ 375/* -- Sweep phase --------------------------------------------------------- */
357 376
358/* Try to shrink some common data structures. */
359static void gc_shrink(global_State *g, lua_State *L)
360{
361 if (g->strnum <= (g->strmask >> 2) && g->strmask > LJ_MIN_STRTAB*2-1)
362 lj_str_resize(L, g->strmask >> 1); /* Shrink string table. */
363 if (g->tmpbuf.sz > LJ_MIN_SBUF*2)
364 lj_str_resizebuf(L, &g->tmpbuf, g->tmpbuf.sz >> 1); /* Shrink temp buf. */
365}
366
367/* Type of GC free functions. */ 377/* Type of GC free functions. */
368typedef void (LJ_FASTCALL *GCFreeFunc)(global_State *g, GCobj *o); 378typedef void (LJ_FASTCALL *GCFreeFunc)(global_State *g, GCobj *o);
369 379
@@ -389,7 +399,7 @@ static const GCFreeFunc gc_freefunc[] = {
389}; 399};
390 400
391/* Full sweep of a GC list. */ 401/* Full sweep of a GC list. */
392#define gc_fullsweep(g, p) gc_sweep(g, (p), LJ_MAX_MEM) 402#define gc_fullsweep(g, p) gc_sweep(g, (p), ~(uint32_t)0)
393 403
394/* Partial sweep of a GC list. */ 404/* Partial sweep of a GC list. */
395static GCRef *gc_sweep(global_State *g, GCRef *p, uint32_t lim) 405static GCRef *gc_sweep(global_State *g, GCRef *p, uint32_t lim)
@@ -401,11 +411,13 @@ static GCRef *gc_sweep(global_State *g, GCRef *p, uint32_t lim)
401 if (o->gch.gct == ~LJ_TTHREAD) /* Need to sweep open upvalues, too. */ 411 if (o->gch.gct == ~LJ_TTHREAD) /* Need to sweep open upvalues, too. */
402 gc_fullsweep(g, &gco2th(o)->openupval); 412 gc_fullsweep(g, &gco2th(o)->openupval);
403 if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */ 413 if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */
404 lua_assert(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED)); 414 lj_assertG(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED),
415 "sweep of undead object");
405 makewhite(g, o); /* Value is alive, change to the current white. */ 416 makewhite(g, o); /* Value is alive, change to the current white. */
406 p = &o->gch.nextgc; 417 p = &o->gch.nextgc;
407 } else { /* Otherwise value is dead, free it. */ 418 } else { /* Otherwise value is dead, free it. */
408 lua_assert(isdead(g, o) || ow == LJ_GC_SFIXED); 419 lj_assertG(isdead(g, o) || ow == LJ_GC_SFIXED,
420 "sweep of unlive object");
409 setgcrefr(*p, o->gch.nextgc); 421 setgcrefr(*p, o->gch.nextgc);
410 if (o == gcref(g->gc.root)) 422 if (o == gcref(g->gc.root))
411 setgcrefr(g->gc.root, o->gch.nextgc); /* Adjust list anchor. */ 423 setgcrefr(g->gc.root, o->gch.nextgc); /* Adjust list anchor. */
@@ -415,6 +427,32 @@ static GCRef *gc_sweep(global_State *g, GCRef *p, uint32_t lim)
415 return p; 427 return p;
416} 428}
417 429
430/* Sweep one string interning table chain. Preserves hashalg bit. */
431static void gc_sweepstr(global_State *g, GCRef *chain)
432{
433 /* Mask with other white and LJ_GC_FIXED. Or LJ_GC_SFIXED on shutdown. */
434 int ow = otherwhite(g);
435 uintptr_t u = gcrefu(*chain);
436 GCRef q;
437 GCRef *p = &q;
438 GCobj *o;
439 setgcrefp(q, (u & ~(uintptr_t)1));
440 while ((o = gcref(*p)) != NULL) {
441 if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */
442 lj_assertG(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED),
443 "sweep of undead string");
444 makewhite(g, o); /* String is alive, change to the current white. */
445 p = &o->gch.nextgc;
446 } else { /* Otherwise string is dead, free it. */
447 lj_assertG(isdead(g, o) || ow == LJ_GC_SFIXED,
448 "sweep of unlive string");
449 setgcrefr(*p, o->gch.nextgc);
450 lj_str_free(g, gco2str(o));
451 }
452 }
453 setgcrefp(*chain, (gcrefu(q) | (u & 1)));
454}
455
418/* Check whether we can clear a key or a value slot from a table. */ 456/* Check whether we can clear a key or a value slot from a table. */
419static int gc_mayclear(cTValue *o, int val) 457static int gc_mayclear(cTValue *o, int val)
420{ 458{
@@ -432,11 +470,12 @@ static int gc_mayclear(cTValue *o, int val)
432} 470}
433 471
434/* Clear collected entries from weak tables. */ 472/* Clear collected entries from weak tables. */
435static void gc_clearweak(GCobj *o) 473static void gc_clearweak(global_State *g, GCobj *o)
436{ 474{
475 UNUSED(g);
437 while (o) { 476 while (o) {
438 GCtab *t = gco2tab(o); 477 GCtab *t = gco2tab(o);
439 lua_assert((t->marked & LJ_GC_WEAK)); 478 lj_assertG((t->marked & LJ_GC_WEAK), "clear of non-weak table");
440 if ((t->marked & LJ_GC_WEAKVAL)) { 479 if ((t->marked & LJ_GC_WEAKVAL)) {
441 MSize i, asize = t->asize; 480 MSize i, asize = t->asize;
442 for (i = 0; i < asize; i++) { 481 for (i = 0; i < asize; i++) {
@@ -467,21 +506,29 @@ static void gc_call_finalizer(global_State *g, lua_State *L,
467{ 506{
468 /* Save and restore lots of state around the __gc callback. */ 507 /* Save and restore lots of state around the __gc callback. */
469 uint8_t oldh = hook_save(g); 508 uint8_t oldh = hook_save(g);
470 MSize oldt = g->gc.threshold; 509 GCSize oldt = g->gc.threshold;
471 int errcode; 510 int errcode;
472 TValue *top; 511 TValue *top;
473 lj_trace_abort(g); 512 lj_trace_abort(g);
474 top = L->top;
475 L->top = top+2;
476 hook_entergc(g); /* Disable hooks and new traces during __gc. */ 513 hook_entergc(g); /* Disable hooks and new traces during __gc. */
514 if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g);
477 g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */ 515 g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */
478 copyTV(L, top, mo); 516 top = L->top;
479 setgcV(L, top+1, o, ~o->gch.gct); 517 copyTV(L, top++, mo);
480 errcode = lj_vm_pcall(L, top+1, 1+0, -1); /* Stack: |mo|o| -> | */ 518 if (LJ_FR2) setnilV(top++);
519 setgcV(L, top, o, ~o->gch.gct);
520 L->top = top+1;
521 errcode = lj_vm_pcall(L, top, 1+0, -1); /* Stack: |mo|o| -> | */
481 hook_restore(g, oldh); 522 hook_restore(g, oldh);
523 if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g);
482 g->gc.threshold = oldt; /* Restore GC threshold. */ 524 g->gc.threshold = oldt; /* Restore GC threshold. */
483 if (errcode) 525 if (errcode) {
484 lj_err_throw(L, errcode); /* Propagate errors. */ 526 ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */
527 lj_vmevent_send(L, ERRFIN,
528 copyTV(L, L->top++, restorestack(L, errobj));
529 );
530 L->top--;
531 }
485} 532}
486 533
487/* Finalize one userdata or cdata object from the mmudata list. */ 534/* Finalize one userdata or cdata object from the mmudata list. */
@@ -490,7 +537,7 @@ static void gc_finalize(lua_State *L)
490 global_State *g = G(L); 537 global_State *g = G(L);
491 GCobj *o = gcnext(gcref(g->gc.mmudata)); 538 GCobj *o = gcnext(gcref(g->gc.mmudata));
492 cTValue *mo; 539 cTValue *mo;
493 lua_assert(gcref(g->jit_L) == NULL); /* Must not be called on trace. */ 540 lj_assertG(tvref(g->jit_base) == NULL, "finalizer called on trace");
494 /* Unchain from list of userdata to be finalized. */ 541 /* Unchain from list of userdata to be finalized. */
495 if (o == gcref(g->gc.mmudata)) 542 if (o == gcref(g->gc.mmudata))
496 setgcrefnull(g->gc.mmudata); 543 setgcrefnull(g->gc.mmudata);
@@ -565,9 +612,9 @@ void lj_gc_freeall(global_State *g)
565 /* Free everything, except super-fixed objects (the main thread). */ 612 /* Free everything, except super-fixed objects (the main thread). */
566 g->gc.currentwhite = LJ_GC_WHITES | LJ_GC_SFIXED; 613 g->gc.currentwhite = LJ_GC_WHITES | LJ_GC_SFIXED;
567 gc_fullsweep(g, &g->gc.root); 614 gc_fullsweep(g, &g->gc.root);
568 strmask = g->strmask; 615 strmask = g->str.mask;
569 for (i = 0; i <= strmask; i++) /* Free all string hash chains. */ 616 for (i = 0; i <= strmask; i++) /* Free all string hash chains. */
570 gc_fullsweep(g, &g->strhash[i]); 617 gc_sweepstr(g, &g->str.tab[i]);
571} 618}
572 619
573/* -- Collector ----------------------------------------------------------- */ 620/* -- Collector ----------------------------------------------------------- */
@@ -582,7 +629,7 @@ static void atomic(global_State *g, lua_State *L)
582 629
583 setgcrefr(g->gc.gray, g->gc.weak); /* Empty the list of weak tables. */ 630 setgcrefr(g->gc.gray, g->gc.weak); /* Empty the list of weak tables. */
584 setgcrefnull(g->gc.weak); 631 setgcrefnull(g->gc.weak);
585 lua_assert(!iswhite(obj2gco(mainthread(g)))); 632 lj_assertG(!iswhite(obj2gco(mainthread(g))), "main thread turned white");
586 gc_markobj(g, L); /* Mark running thread. */ 633 gc_markobj(g, L); /* Mark running thread. */
587 gc_traverse_curtrace(g); /* Traverse current trace. */ 634 gc_traverse_curtrace(g); /* Traverse current trace. */
588 gc_mark_gcroot(g); /* Mark GC roots (again). */ 635 gc_mark_gcroot(g); /* Mark GC roots (again). */
@@ -597,13 +644,15 @@ static void atomic(global_State *g, lua_State *L)
597 udsize += gc_propagate_gray(g); /* And propagate the marks. */ 644 udsize += gc_propagate_gray(g); /* And propagate the marks. */
598 645
599 /* All marking done, clear weak tables. */ 646 /* All marking done, clear weak tables. */
600 gc_clearweak(gcref(g->gc.weak)); 647 gc_clearweak(g, gcref(g->gc.weak));
648
649 lj_buf_shrink(L, &g->tmpbuf); /* Shrink temp buffer. */
601 650
602 /* Prepare for sweep phase. */ 651 /* Prepare for sweep phase. */
603 g->gc.currentwhite = (uint8_t)otherwhite(g); /* Flip current white. */ 652 g->gc.currentwhite = (uint8_t)otherwhite(g); /* Flip current white. */
604 g->strempty.marked = g->gc.currentwhite; 653 g->strempty.marked = g->gc.currentwhite;
605 setmref(g->gc.sweep, &g->gc.root); 654 setmref(g->gc.sweep, &g->gc.root);
606 g->gc.estimate = g->gc.total - (MSize)udsize; /* Initial estimate. */ 655 g->gc.estimate = g->gc.total - (GCSize)udsize; /* Initial estimate. */
607} 656}
608 657
609/* GC state machine. Returns a cost estimate for each step performed. */ 658/* GC state machine. Returns a cost estimate for each step performed. */
@@ -620,28 +669,29 @@ static size_t gc_onestep(lua_State *L)
620 g->gc.state = GCSatomic; /* End of mark phase. */ 669 g->gc.state = GCSatomic; /* End of mark phase. */
621 return 0; 670 return 0;
622 case GCSatomic: 671 case GCSatomic:
623 if (gcref(g->jit_L)) /* Don't run atomic phase on trace. */ 672 if (tvref(g->jit_base)) /* Don't run atomic phase on trace. */
624 return LJ_MAX_MEM; 673 return LJ_MAX_MEM;
625 atomic(g, L); 674 atomic(g, L);
626 g->gc.state = GCSsweepstring; /* Start of sweep phase. */ 675 g->gc.state = GCSsweepstring; /* Start of sweep phase. */
627 g->gc.sweepstr = 0; 676 g->gc.sweepstr = 0;
628 return 0; 677 return 0;
629 case GCSsweepstring: { 678 case GCSsweepstring: {
630 MSize old = g->gc.total; 679 GCSize old = g->gc.total;
631 gc_fullsweep(g, &g->strhash[g->gc.sweepstr++]); /* Sweep one chain. */ 680 gc_sweepstr(g, &g->str.tab[g->gc.sweepstr++]); /* Sweep one chain. */
632 if (g->gc.sweepstr > g->strmask) 681 if (g->gc.sweepstr > g->str.mask)
633 g->gc.state = GCSsweep; /* All string hash chains sweeped. */ 682 g->gc.state = GCSsweep; /* All string hash chains sweeped. */
634 lua_assert(old >= g->gc.total); 683 lj_assertG(old >= g->gc.total, "sweep increased memory");
635 g->gc.estimate -= old - g->gc.total; 684 g->gc.estimate -= old - g->gc.total;
636 return GCSWEEPCOST; 685 return GCSWEEPCOST;
637 } 686 }
638 case GCSsweep: { 687 case GCSsweep: {
639 MSize old = g->gc.total; 688 GCSize old = g->gc.total;
640 setmref(g->gc.sweep, gc_sweep(g, mref(g->gc.sweep, GCRef), GCSWEEPMAX)); 689 setmref(g->gc.sweep, gc_sweep(g, mref(g->gc.sweep, GCRef), GCSWEEPMAX));
641 lua_assert(old >= g->gc.total); 690 lj_assertG(old >= g->gc.total, "sweep increased memory");
642 g->gc.estimate -= old - g->gc.total; 691 g->gc.estimate -= old - g->gc.total;
643 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) { 692 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) {
644 gc_shrink(g, L); 693 if (g->str.num <= (g->str.mask >> 2) && g->str.mask > LJ_MIN_STRTAB*2-1)
694 lj_str_resize(L, g->str.mask >> 1); /* Shrink string table. */
645 if (gcref(g->gc.mmudata)) { /* Need any finalizations? */ 695 if (gcref(g->gc.mmudata)) { /* Need any finalizations? */
646 g->gc.state = GCSfinalize; 696 g->gc.state = GCSfinalize;
647#if LJ_HASFFI 697#if LJ_HASFFI
@@ -656,9 +706,12 @@ static size_t gc_onestep(lua_State *L)
656 } 706 }
657 case GCSfinalize: 707 case GCSfinalize:
658 if (gcref(g->gc.mmudata) != NULL) { 708 if (gcref(g->gc.mmudata) != NULL) {
659 if (gcref(g->jit_L)) /* Don't call finalizers on trace. */ 709 GCSize old = g->gc.total;
710 if (tvref(g->jit_base)) /* Don't call finalizers on trace. */
660 return LJ_MAX_MEM; 711 return LJ_MAX_MEM;
661 gc_finalize(L); /* Finalize one userdata object. */ 712 gc_finalize(L); /* Finalize one userdata object. */
713 if (old >= g->gc.total && g->gc.estimate > old - g->gc.total)
714 g->gc.estimate -= old - g->gc.total;
662 if (g->gc.estimate > GCFINALIZECOST) 715 if (g->gc.estimate > GCFINALIZECOST)
663 g->gc.estimate -= GCFINALIZECOST; 716 g->gc.estimate -= GCFINALIZECOST;
664 return GCFINALIZECOST; 717 return GCFINALIZECOST;
@@ -670,7 +723,7 @@ static size_t gc_onestep(lua_State *L)
670 g->gc.debt = 0; 723 g->gc.debt = 0;
671 return 0; 724 return 0;
672 default: 725 default:
673 lua_assert(0); 726 lj_assertG(0, "bad GC state");
674 return 0; 727 return 0;
675 } 728 }
676} 729}
@@ -679,7 +732,7 @@ static size_t gc_onestep(lua_State *L)
679int LJ_FASTCALL lj_gc_step(lua_State *L) 732int LJ_FASTCALL lj_gc_step(lua_State *L)
680{ 733{
681 global_State *g = G(L); 734 global_State *g = G(L);
682 MSize lim; 735 GCSize lim;
683 int32_t ostate = g->vmstate; 736 int32_t ostate = g->vmstate;
684 setvmstate(g, GC); 737 setvmstate(g, GC);
685 lim = (GCSTEPSIZE/100) * g->gc.stepmul; 738 lim = (GCSTEPSIZE/100) * g->gc.stepmul;
@@ -688,13 +741,13 @@ int LJ_FASTCALL lj_gc_step(lua_State *L)
688 if (g->gc.total > g->gc.threshold) 741 if (g->gc.total > g->gc.threshold)
689 g->gc.debt += g->gc.total - g->gc.threshold; 742 g->gc.debt += g->gc.total - g->gc.threshold;
690 do { 743 do {
691 lim -= (MSize)gc_onestep(L); 744 lim -= (GCSize)gc_onestep(L);
692 if (g->gc.state == GCSpause) { 745 if (g->gc.state == GCSpause) {
693 g->gc.threshold = (g->gc.estimate/100) * g->gc.pause; 746 g->gc.threshold = (g->gc.estimate/100) * g->gc.pause;
694 g->vmstate = ostate; 747 g->vmstate = ostate;
695 return 1; /* Finished a GC cycle. */ 748 return 1; /* Finished a GC cycle. */
696 } 749 }
697 } while ((int32_t)lim > 0); 750 } while (sizeof(lim) == 8 ? ((int64_t)lim > 0) : ((int32_t)lim > 0));
698 if (g->gc.debt < GCSTEPSIZE) { 751 if (g->gc.debt < GCSTEPSIZE) {
699 g->gc.threshold = g->gc.total + GCSTEPSIZE; 752 g->gc.threshold = g->gc.total + GCSTEPSIZE;
700 g->vmstate = ostate; 753 g->vmstate = ostate;
@@ -718,8 +771,8 @@ void LJ_FASTCALL lj_gc_step_fixtop(lua_State *L)
718/* Perform multiple GC steps. Called from JIT-compiled code. */ 771/* Perform multiple GC steps. Called from JIT-compiled code. */
719int LJ_FASTCALL lj_gc_step_jit(global_State *g, MSize steps) 772int LJ_FASTCALL lj_gc_step_jit(global_State *g, MSize steps)
720{ 773{
721 lua_State *L = gco2th(gcref(g->jit_L)); 774 lua_State *L = gco2th(gcref(g->cur_L));
722 L->base = mref(G(L)->jit_base, TValue); 775 L->base = tvref(G(L)->jit_base);
723 L->top = curr_topL(L); 776 L->top = curr_topL(L);
724 while (steps-- > 0 && lj_gc_step(L) == 0) 777 while (steps-- > 0 && lj_gc_step(L) == 0)
725 ; 778 ;
@@ -744,7 +797,8 @@ void lj_gc_fullgc(lua_State *L)
744 } 797 }
745 while (g->gc.state == GCSsweepstring || g->gc.state == GCSsweep) 798 while (g->gc.state == GCSsweepstring || g->gc.state == GCSsweep)
746 gc_onestep(L); /* Finish sweep. */ 799 gc_onestep(L); /* Finish sweep. */
747 lua_assert(g->gc.state == GCSfinalize || g->gc.state == GCSpause); 800 lj_assertG(g->gc.state == GCSfinalize || g->gc.state == GCSpause,
801 "bad GC state");
748 /* Now perform a full GC. */ 802 /* Now perform a full GC. */
749 g->gc.state = GCSpause; 803 g->gc.state = GCSpause;
750 do { gc_onestep(L); } while (g->gc.state != GCSpause); 804 do { gc_onestep(L); } while (g->gc.state != GCSpause);
@@ -757,9 +811,11 @@ void lj_gc_fullgc(lua_State *L)
757/* Move the GC propagation frontier forward. */ 811/* Move the GC propagation frontier forward. */
758void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v) 812void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v)
759{ 813{
760 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); 814 lj_assertG(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o),
761 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause); 815 "bad object states for forward barrier");
762 lua_assert(o->gch.gct != ~LJ_TTAB); 816 lj_assertG(g->gc.state != GCSfinalize && g->gc.state != GCSpause,
817 "bad GC state");
818 lj_assertG(o->gch.gct != ~LJ_TTAB, "barrier object is not a table");
763 /* Preserve invariant during propagation. Otherwise it doesn't matter. */ 819 /* Preserve invariant during propagation. Otherwise it doesn't matter. */
764 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic) 820 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
765 gc_mark(g, v); /* Move frontier forward. */ 821 gc_mark(g, v); /* Move frontier forward. */
@@ -796,7 +852,8 @@ void lj_gc_closeuv(global_State *g, GCupval *uv)
796 lj_gc_barrierf(g, o, gcV(&uv->tv)); 852 lj_gc_barrierf(g, o, gcV(&uv->tv));
797 } else { 853 } else {
798 makewhite(g, o); /* Make it white, i.e. sweep the upvalue. */ 854 makewhite(g, o); /* Make it white, i.e. sweep the upvalue. */
799 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause); 855 lj_assertG(g->gc.state != GCSfinalize && g->gc.state != GCSpause,
856 "bad GC state");
800 } 857 }
801 } 858 }
802} 859}
@@ -813,27 +870,29 @@ void lj_gc_barriertrace(global_State *g, uint32_t traceno)
813/* -- Allocator ----------------------------------------------------------- */ 870/* -- Allocator ----------------------------------------------------------- */
814 871
815/* Call pluggable memory allocator to allocate or resize a fragment. */ 872/* Call pluggable memory allocator to allocate or resize a fragment. */
816void *lj_mem_realloc(lua_State *L, void *p, MSize osz, MSize nsz) 873void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz)
817{ 874{
818 global_State *g = G(L); 875 global_State *g = G(L);
819 lua_assert((osz == 0) == (p == NULL)); 876 lj_assertG((osz == 0) == (p == NULL), "realloc API violation");
820 p = g->allocf(g->allocd, p, osz, nsz); 877 p = g->allocf(g->allocd, p, osz, nsz);
821 if (p == NULL && nsz > 0) 878 if (p == NULL && nsz > 0)
822 lj_err_mem(L); 879 lj_err_mem(L);
823 lua_assert((nsz == 0) == (p == NULL)); 880 lj_assertG((nsz == 0) == (p == NULL), "allocf API violation");
824 lua_assert(checkptr32(p)); 881 lj_assertG(checkptrGC(p),
882 "allocated memory address %p outside required range", p);
825 g->gc.total = (g->gc.total - osz) + nsz; 883 g->gc.total = (g->gc.total - osz) + nsz;
826 return p; 884 return p;
827} 885}
828 886
829/* Allocate new GC object and link it to the root set. */ 887/* Allocate new GC object and link it to the root set. */
830void * LJ_FASTCALL lj_mem_newgco(lua_State *L, MSize size) 888void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size)
831{ 889{
832 global_State *g = G(L); 890 global_State *g = G(L);
833 GCobj *o = (GCobj *)g->allocf(g->allocd, NULL, 0, size); 891 GCobj *o = (GCobj *)g->allocf(g->allocd, NULL, 0, size);
834 if (o == NULL) 892 if (o == NULL)
835 lj_err_mem(L); 893 lj_err_mem(L);
836 lua_assert(checkptr32(o)); 894 lj_assertG(checkptrGC(o),
895 "allocated memory address %p outside required range", o);
837 g->gc.total += size; 896 g->gc.total += size;
838 setgcrefr(o->gch.nextgc, g->gc.root); 897 setgcrefr(o->gch.nextgc, g->gc.root);
839 setgcref(g->gc.root, o); 898 setgcref(g->gc.root, o);