aboutsummaryrefslogtreecommitdiff
path: root/src/lj_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_gc.c')
-rw-r--r--src/lj_gc.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 671b5983..cc4232a6 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -417,6 +417,32 @@ static GCRef *gc_sweep(global_State *g, GCRef *p, uint32_t lim)
417 return p; 417 return p;
418} 418}
419 419
420/* Sweep one string interning table chain. Preserves hashalg bit. */
421static void gc_sweepstr(global_State *g, GCRef *chain)
422{
423 /* Mask with other white and LJ_GC_FIXED. Or LJ_GC_SFIXED on shutdown. */
424 int ow = otherwhite(g);
425 uintptr_t u = gcrefu(*chain);
426 GCRef q;
427 GCRef *p = &q;
428 GCobj *o;
429 setgcrefp(q, (u & ~(uintptr_t)1));
430 while ((o = gcref(*p)) != NULL) {
431 if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */
432 lj_assertG(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED),
433 "sweep of undead string");
434 makewhite(g, o); /* String is alive, change to the current white. */
435 p = &o->gch.nextgc;
436 } else { /* Otherwise string is dead, free it. */
437 lj_assertG(isdead(g, o) || ow == LJ_GC_SFIXED,
438 "sweep of unlive string");
439 setgcrefr(*p, o->gch.nextgc);
440 lj_str_free(g, gco2str(o));
441 }
442 }
443 setgcrefp(*chain, (gcrefu(q) | (u & 1)));
444}
445
420/* Check whether we can clear a key or a value slot from a table. */ 446/* Check whether we can clear a key or a value slot from a table. */
421static int gc_mayclear(cTValue *o, int val) 447static int gc_mayclear(cTValue *o, int val)
422{ 448{
@@ -571,9 +597,9 @@ void lj_gc_freeall(global_State *g)
571 /* Free everything, except super-fixed objects (the main thread). */ 597 /* Free everything, except super-fixed objects (the main thread). */
572 g->gc.currentwhite = LJ_GC_WHITES | LJ_GC_SFIXED; 598 g->gc.currentwhite = LJ_GC_WHITES | LJ_GC_SFIXED;
573 gc_fullsweep(g, &g->gc.root); 599 gc_fullsweep(g, &g->gc.root);
574 strmask = g->strmask; 600 strmask = g->str.mask;
575 for (i = 0; i <= strmask; i++) /* Free all string hash chains. */ 601 for (i = 0; i <= strmask; i++) /* Free all string hash chains. */
576 gc_fullsweep(g, &g->strhash[i]); 602 gc_sweepstr(g, &g->str.tab[i]);
577} 603}
578 604
579/* -- Collector ----------------------------------------------------------- */ 605/* -- Collector ----------------------------------------------------------- */
@@ -636,8 +662,8 @@ static size_t gc_onestep(lua_State *L)
636 return 0; 662 return 0;
637 case GCSsweepstring: { 663 case GCSsweepstring: {
638 GCSize old = g->gc.total; 664 GCSize old = g->gc.total;
639 gc_fullsweep(g, &g->strhash[g->gc.sweepstr++]); /* Sweep one chain. */ 665 gc_sweepstr(g, &g->str.tab[g->gc.sweepstr++]); /* Sweep one chain. */
640 if (g->gc.sweepstr > g->strmask) 666 if (g->gc.sweepstr > g->str.mask)
641 g->gc.state = GCSsweep; /* All string hash chains sweeped. */ 667 g->gc.state = GCSsweep; /* All string hash chains sweeped. */
642 lj_assertG(old >= g->gc.total, "sweep increased memory"); 668 lj_assertG(old >= g->gc.total, "sweep increased memory");
643 g->gc.estimate -= old - g->gc.total; 669 g->gc.estimate -= old - g->gc.total;
@@ -649,8 +675,8 @@ static size_t gc_onestep(lua_State *L)
649 lj_assertG(old >= g->gc.total, "sweep increased memory"); 675 lj_assertG(old >= g->gc.total, "sweep increased memory");
650 g->gc.estimate -= old - g->gc.total; 676 g->gc.estimate -= old - g->gc.total;
651 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) { 677 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) {
652 if (g->strnum <= (g->strmask >> 2) && g->strmask > LJ_MIN_STRTAB*2-1) 678 if (g->str.num <= (g->str.mask >> 2) && g->str.mask > LJ_MIN_STRTAB*2-1)
653 lj_str_resize(L, g->strmask >> 1); /* Shrink string table. */ 679 lj_str_resize(L, g->str.mask >> 1); /* Shrink string table. */
654 if (gcref(g->gc.mmudata)) { /* Need any finalizations? */ 680 if (gcref(g->gc.mmudata)) { /* Need any finalizations? */
655 g->gc.state = GCSfinalize; 681 g->gc.state = GCSfinalize;
656#if LJ_HASFFI 682#if LJ_HASFFI