aboutsummaryrefslogtreecommitdiff
path: root/src/lj_gc.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_gc.c72
1 files changed, 43 insertions, 29 deletions
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 81439aab..671b5983 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -42,7 +42,8 @@
42 42
43/* Mark a TValue (if needed). */ 43/* Mark a TValue (if needed). */
44#define gc_marktv(g, tv) \ 44#define gc_marktv(g, tv) \
45 { lua_assert(!tvisgcv(tv) || (~itype(tv) == gcval(tv)->gch.gct)); \ 45 { lj_assertG(!tvisgcv(tv) || (~itype(tv) == gcval(tv)->gch.gct), \
46 "TValue and GC type mismatch"); \
46 if (tviswhite(tv)) gc_mark(g, gcV(tv)); } 47 if (tviswhite(tv)) gc_mark(g, gcV(tv)); }
47 48
48/* Mark a GCobj (if needed). */ 49/* Mark a GCobj (if needed). */
@@ -56,7 +57,8 @@
56static void gc_mark(global_State *g, GCobj *o) 57static void gc_mark(global_State *g, GCobj *o)
57{ 58{
58 int gct = o->gch.gct; 59 int gct = o->gch.gct;
59 lua_assert(iswhite(o) && !isdead(g, o)); 60 lj_assertG(iswhite(o), "mark of non-white object");
61 lj_assertG(!isdead(g, o), "mark of dead object");
60 white2gray(o); 62 white2gray(o);
61 if (LJ_UNLIKELY(gct == ~LJ_TUDATA)) { 63 if (LJ_UNLIKELY(gct == ~LJ_TUDATA)) {
62 GCtab *mt = tabref(gco2ud(o)->metatable); 64 GCtab *mt = tabref(gco2ud(o)->metatable);
@@ -69,8 +71,9 @@ static void gc_mark(global_State *g, GCobj *o)
69 if (uv->closed) 71 if (uv->closed)
70 gray2black(o); /* Closed upvalues are never gray. */ 72 gray2black(o); /* Closed upvalues are never gray. */
71 } else if (gct != ~LJ_TSTR && gct != ~LJ_TCDATA) { 73 } else if (gct != ~LJ_TSTR && gct != ~LJ_TCDATA) {
72 lua_assert(gct == ~LJ_TFUNC || gct == ~LJ_TTAB || 74 lj_assertG(gct == ~LJ_TFUNC || gct == ~LJ_TTAB ||
73 gct == ~LJ_TTHREAD || gct == ~LJ_TPROTO || gct == ~LJ_TTRACE); 75 gct == ~LJ_TTHREAD || gct == ~LJ_TPROTO || gct == ~LJ_TTRACE,
76 "bad GC type %d", gct);
74 setgcrefr(o->gch.gclist, g->gc.gray); 77 setgcrefr(o->gch.gclist, g->gc.gray);
75 setgcref(g->gc.gray, o); 78 setgcref(g->gc.gray, o);
76 } 79 }
@@ -103,7 +106,8 @@ static void gc_mark_uv(global_State *g)
103{ 106{
104 GCupval *uv; 107 GCupval *uv;
105 for (uv = uvnext(&g->uvhead); uv != &g->uvhead; uv = uvnext(uv)) { 108 for (uv = uvnext(&g->uvhead); uv != &g->uvhead; uv = uvnext(uv)) {
106 lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv); 109 lj_assertG(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv,
110 "broken upvalue chain");
107 if (isgray(obj2gco(uv))) 111 if (isgray(obj2gco(uv)))
108 gc_marktv(g, uvval(uv)); 112 gc_marktv(g, uvval(uv));
109 } 113 }
@@ -198,7 +202,7 @@ static int gc_traverse_tab(global_State *g, GCtab *t)
198 for (i = 0; i <= hmask; i++) { 202 for (i = 0; i <= hmask; i++) {
199 Node *n = &node[i]; 203 Node *n = &node[i];
200 if (!tvisnil(&n->val)) { /* Mark non-empty slot. */ 204 if (!tvisnil(&n->val)) { /* Mark non-empty slot. */
201 lua_assert(!tvisnil(&n->key)); 205 lj_assertG(!tvisnil(&n->key), "mark of nil key in non-empty slot");
202 if (!(weak & LJ_GC_WEAKKEY)) gc_marktv(g, &n->key); 206 if (!(weak & LJ_GC_WEAKKEY)) gc_marktv(g, &n->key);
203 if (!(weak & LJ_GC_WEAKVAL)) gc_marktv(g, &n->val); 207 if (!(weak & LJ_GC_WEAKVAL)) gc_marktv(g, &n->val);
204 } 208 }
@@ -213,7 +217,8 @@ static void gc_traverse_func(global_State *g, GCfunc *fn)
213 gc_markobj(g, tabref(fn->c.env)); 217 gc_markobj(g, tabref(fn->c.env));
214 if (isluafunc(fn)) { 218 if (isluafunc(fn)) {
215 uint32_t i; 219 uint32_t i;
216 lua_assert(fn->l.nupvalues <= funcproto(fn)->sizeuv); 220 lj_assertG(fn->l.nupvalues <= funcproto(fn)->sizeuv,
221 "function upvalues out of range");
217 gc_markobj(g, funcproto(fn)); 222 gc_markobj(g, funcproto(fn));
218 for (i = 0; i < fn->l.nupvalues; i++) /* Mark Lua function upvalues. */ 223 for (i = 0; i < fn->l.nupvalues; i++) /* Mark Lua function upvalues. */
219 gc_markobj(g, &gcref(fn->l.uvptr[i])->uv); 224 gc_markobj(g, &gcref(fn->l.uvptr[i])->uv);
@@ -229,7 +234,7 @@ static void gc_traverse_func(global_State *g, GCfunc *fn)
229static void gc_marktrace(global_State *g, TraceNo traceno) 234static void gc_marktrace(global_State *g, TraceNo traceno)
230{ 235{
231 GCobj *o = obj2gco(traceref(G2J(g), traceno)); 236 GCobj *o = obj2gco(traceref(G2J(g), traceno));
232 lua_assert(traceno != G2J(g)->cur.traceno); 237 lj_assertG(traceno != G2J(g)->cur.traceno, "active trace escaped");
233 if (iswhite(o)) { 238 if (iswhite(o)) {
234 white2gray(o); 239 white2gray(o);
235 setgcrefr(o->gch.gclist, g->gc.gray); 240 setgcrefr(o->gch.gclist, g->gc.gray);
@@ -310,7 +315,7 @@ static size_t propagatemark(global_State *g)
310{ 315{
311 GCobj *o = gcref(g->gc.gray); 316 GCobj *o = gcref(g->gc.gray);
312 int gct = o->gch.gct; 317 int gct = o->gch.gct;
313 lua_assert(isgray(o)); 318 lj_assertG(isgray(o), "propagation of non-gray object");
314 gray2black(o); 319 gray2black(o);
315 setgcrefr(g->gc.gray, o->gch.gclist); /* Remove from gray list. */ 320 setgcrefr(g->gc.gray, o->gch.gclist); /* Remove from gray list. */
316 if (LJ_LIKELY(gct == ~LJ_TTAB)) { 321 if (LJ_LIKELY(gct == ~LJ_TTAB)) {
@@ -342,7 +347,7 @@ static size_t propagatemark(global_State *g)
342 return ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) + 347 return ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
343 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry); 348 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry);
344#else 349#else
345 lua_assert(0); 350 lj_assertG(0, "bad GC type %d", gct);
346 return 0; 351 return 0;
347#endif 352#endif
348 } 353 }
@@ -396,11 +401,13 @@ static GCRef *gc_sweep(global_State *g, GCRef *p, uint32_t lim)
396 if (o->gch.gct == ~LJ_TTHREAD) /* Need to sweep open upvalues, too. */ 401 if (o->gch.gct == ~LJ_TTHREAD) /* Need to sweep open upvalues, too. */
397 gc_fullsweep(g, &gco2th(o)->openupval); 402 gc_fullsweep(g, &gco2th(o)->openupval);
398 if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */ 403 if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */
399 lua_assert(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED)); 404 lj_assertG(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED),
405 "sweep of undead object");
400 makewhite(g, o); /* Value is alive, change to the current white. */ 406 makewhite(g, o); /* Value is alive, change to the current white. */
401 p = &o->gch.nextgc; 407 p = &o->gch.nextgc;
402 } else { /* Otherwise value is dead, free it. */ 408 } else { /* Otherwise value is dead, free it. */
403 lua_assert(isdead(g, o) || ow == LJ_GC_SFIXED); 409 lj_assertG(isdead(g, o) || ow == LJ_GC_SFIXED,
410 "sweep of unlive object");
404 setgcrefr(*p, o->gch.nextgc); 411 setgcrefr(*p, o->gch.nextgc);
405 if (o == gcref(g->gc.root)) 412 if (o == gcref(g->gc.root))
406 setgcrefr(g->gc.root, o->gch.nextgc); /* Adjust list anchor. */ 413 setgcrefr(g->gc.root, o->gch.nextgc); /* Adjust list anchor. */
@@ -427,11 +434,12 @@ static int gc_mayclear(cTValue *o, int val)
427} 434}
428 435
429/* Clear collected entries from weak tables. */ 436/* Clear collected entries from weak tables. */
430static void gc_clearweak(GCobj *o) 437static void gc_clearweak(global_State *g, GCobj *o)
431{ 438{
439 UNUSED(g);
432 while (o) { 440 while (o) {
433 GCtab *t = gco2tab(o); 441 GCtab *t = gco2tab(o);
434 lua_assert((t->marked & LJ_GC_WEAK)); 442 lj_assertG((t->marked & LJ_GC_WEAK), "clear of non-weak table");
435 if ((t->marked & LJ_GC_WEAKVAL)) { 443 if ((t->marked & LJ_GC_WEAKVAL)) {
436 MSize i, asize = t->asize; 444 MSize i, asize = t->asize;
437 for (i = 0; i < asize; i++) { 445 for (i = 0; i < asize; i++) {
@@ -488,7 +496,7 @@ static void gc_finalize(lua_State *L)
488 global_State *g = G(L); 496 global_State *g = G(L);
489 GCobj *o = gcnext(gcref(g->gc.mmudata)); 497 GCobj *o = gcnext(gcref(g->gc.mmudata));
490 cTValue *mo; 498 cTValue *mo;
491 lua_assert(tvref(g->jit_base) == NULL); /* Must not be called on trace. */ 499 lj_assertG(tvref(g->jit_base) == NULL, "finalizer called on trace");
492 /* Unchain from list of userdata to be finalized. */ 500 /* Unchain from list of userdata to be finalized. */
493 if (o == gcref(g->gc.mmudata)) 501 if (o == gcref(g->gc.mmudata))
494 setgcrefnull(g->gc.mmudata); 502 setgcrefnull(g->gc.mmudata);
@@ -580,7 +588,7 @@ static void atomic(global_State *g, lua_State *L)
580 588
581 setgcrefr(g->gc.gray, g->gc.weak); /* Empty the list of weak tables. */ 589 setgcrefr(g->gc.gray, g->gc.weak); /* Empty the list of weak tables. */
582 setgcrefnull(g->gc.weak); 590 setgcrefnull(g->gc.weak);
583 lua_assert(!iswhite(obj2gco(mainthread(g)))); 591 lj_assertG(!iswhite(obj2gco(mainthread(g))), "main thread turned white");
584 gc_markobj(g, L); /* Mark running thread. */ 592 gc_markobj(g, L); /* Mark running thread. */
585 gc_traverse_curtrace(g); /* Traverse current trace. */ 593 gc_traverse_curtrace(g); /* Traverse current trace. */
586 gc_mark_gcroot(g); /* Mark GC roots (again). */ 594 gc_mark_gcroot(g); /* Mark GC roots (again). */
@@ -595,7 +603,7 @@ static void atomic(global_State *g, lua_State *L)
595 udsize += gc_propagate_gray(g); /* And propagate the marks. */ 603 udsize += gc_propagate_gray(g); /* And propagate the marks. */
596 604
597 /* All marking done, clear weak tables. */ 605 /* All marking done, clear weak tables. */
598 gc_clearweak(gcref(g->gc.weak)); 606 gc_clearweak(g, gcref(g->gc.weak));
599 607
600 lj_buf_shrink(L, &g->tmpbuf); /* Shrink temp buffer. */ 608 lj_buf_shrink(L, &g->tmpbuf); /* Shrink temp buffer. */
601 609
@@ -631,14 +639,14 @@ static size_t gc_onestep(lua_State *L)
631 gc_fullsweep(g, &g->strhash[g->gc.sweepstr++]); /* Sweep one chain. */ 639 gc_fullsweep(g, &g->strhash[g->gc.sweepstr++]); /* Sweep one chain. */
632 if (g->gc.sweepstr > g->strmask) 640 if (g->gc.sweepstr > g->strmask)
633 g->gc.state = GCSsweep; /* All string hash chains sweeped. */ 641 g->gc.state = GCSsweep; /* All string hash chains sweeped. */
634 lua_assert(old >= g->gc.total); 642 lj_assertG(old >= g->gc.total, "sweep increased memory");
635 g->gc.estimate -= old - g->gc.total; 643 g->gc.estimate -= old - g->gc.total;
636 return GCSWEEPCOST; 644 return GCSWEEPCOST;
637 } 645 }
638 case GCSsweep: { 646 case GCSsweep: {
639 GCSize old = g->gc.total; 647 GCSize old = g->gc.total;
640 setmref(g->gc.sweep, gc_sweep(g, mref(g->gc.sweep, GCRef), GCSWEEPMAX)); 648 setmref(g->gc.sweep, gc_sweep(g, mref(g->gc.sweep, GCRef), GCSWEEPMAX));
641 lua_assert(old >= g->gc.total); 649 lj_assertG(old >= g->gc.total, "sweep increased memory");
642 g->gc.estimate -= old - g->gc.total; 650 g->gc.estimate -= old - g->gc.total;
643 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) { 651 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) {
644 if (g->strnum <= (g->strmask >> 2) && g->strmask > LJ_MIN_STRTAB*2-1) 652 if (g->strnum <= (g->strmask >> 2) && g->strmask > LJ_MIN_STRTAB*2-1)
@@ -671,7 +679,7 @@ static size_t gc_onestep(lua_State *L)
671 g->gc.debt = 0; 679 g->gc.debt = 0;
672 return 0; 680 return 0;
673 default: 681 default:
674 lua_assert(0); 682 lj_assertG(0, "bad GC state");
675 return 0; 683 return 0;
676 } 684 }
677} 685}
@@ -745,7 +753,8 @@ void lj_gc_fullgc(lua_State *L)
745 } 753 }
746 while (g->gc.state == GCSsweepstring || g->gc.state == GCSsweep) 754 while (g->gc.state == GCSsweepstring || g->gc.state == GCSsweep)
747 gc_onestep(L); /* Finish sweep. */ 755 gc_onestep(L); /* Finish sweep. */
748 lua_assert(g->gc.state == GCSfinalize || g->gc.state == GCSpause); 756 lj_assertG(g->gc.state == GCSfinalize || g->gc.state == GCSpause,
757 "bad GC state");
749 /* Now perform a full GC. */ 758 /* Now perform a full GC. */
750 g->gc.state = GCSpause; 759 g->gc.state = GCSpause;
751 do { gc_onestep(L); } while (g->gc.state != GCSpause); 760 do { gc_onestep(L); } while (g->gc.state != GCSpause);
@@ -758,9 +767,11 @@ void lj_gc_fullgc(lua_State *L)
758/* Move the GC propagation frontier forward. */ 767/* Move the GC propagation frontier forward. */
759void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v) 768void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v)
760{ 769{
761 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); 770 lj_assertG(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o),
762 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause); 771 "bad object states for forward barrier");
763 lua_assert(o->gch.gct != ~LJ_TTAB); 772 lj_assertG(g->gc.state != GCSfinalize && g->gc.state != GCSpause,
773 "bad GC state");
774 lj_assertG(o->gch.gct != ~LJ_TTAB, "barrier object is not a table");
764 /* Preserve invariant during propagation. Otherwise it doesn't matter. */ 775 /* Preserve invariant during propagation. Otherwise it doesn't matter. */
765 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic) 776 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
766 gc_mark(g, v); /* Move frontier forward. */ 777 gc_mark(g, v); /* Move frontier forward. */
@@ -797,7 +808,8 @@ void lj_gc_closeuv(global_State *g, GCupval *uv)
797 lj_gc_barrierf(g, o, gcV(&uv->tv)); 808 lj_gc_barrierf(g, o, gcV(&uv->tv));
798 } else { 809 } else {
799 makewhite(g, o); /* Make it white, i.e. sweep the upvalue. */ 810 makewhite(g, o); /* Make it white, i.e. sweep the upvalue. */
800 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause); 811 lj_assertG(g->gc.state != GCSfinalize && g->gc.state != GCSpause,
812 "bad GC state");
801 } 813 }
802 } 814 }
803} 815}
@@ -817,12 +829,13 @@ void lj_gc_barriertrace(global_State *g, uint32_t traceno)
817void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz) 829void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz)
818{ 830{
819 global_State *g = G(L); 831 global_State *g = G(L);
820 lua_assert((osz == 0) == (p == NULL)); 832 lj_assertG((osz == 0) == (p == NULL), "realloc API violation");
821 p = g->allocf(g->allocd, p, osz, nsz); 833 p = g->allocf(g->allocd, p, osz, nsz);
822 if (p == NULL && nsz > 0) 834 if (p == NULL && nsz > 0)
823 lj_err_mem(L); 835 lj_err_mem(L);
824 lua_assert((nsz == 0) == (p == NULL)); 836 lj_assertG((nsz == 0) == (p == NULL), "allocf API violation");
825 lua_assert(checkptrGC(p)); 837 lj_assertG(checkptrGC(p),
838 "allocated memory address %p outside required range", p);
826 g->gc.total = (g->gc.total - osz) + nsz; 839 g->gc.total = (g->gc.total - osz) + nsz;
827 return p; 840 return p;
828} 841}
@@ -834,7 +847,8 @@ void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size)
834 GCobj *o = (GCobj *)g->allocf(g->allocd, NULL, 0, size); 847 GCobj *o = (GCobj *)g->allocf(g->allocd, NULL, 0, size);
835 if (o == NULL) 848 if (o == NULL)
836 lj_err_mem(L); 849 lj_err_mem(L);
837 lua_assert(checkptrGC(o)); 850 lj_assertG(checkptrGC(o),
851 "allocated memory address %p outside required range", o);
838 g->gc.total += size; 852 g->gc.total += size;
839 setgcrefr(o->gch.nextgc, g->gc.root); 853 setgcrefr(o->gch.nextgc, g->gc.root);
840 setgcref(g->gc.root, o); 854 setgcref(g->gc.root, o);