diff options
Diffstat (limited to 'src/lj_gc.c')
-rw-r--r-- | src/lj_gc.c | 38 |
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. */ | ||
421 | static 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. */ |
421 | static int gc_mayclear(cTValue *o, int val) | 447 | static 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 |