private static void GCTM(LinyeeState L) { GlobalState g = G(L); GCObject o = g.tmudata.gch.next; /* get first element */ Udata udata = rawgco2u(o); TValue tm; /* remove udata from `tmudata' */ if (o == g.tmudata) /* last element? */ { g.tmudata = null; } else { g.tmudata.gch.next = udata.uv.next; } udata.uv.next = g.mainthread.next; /* return it to `root' list */ g.mainthread.next = o; MakeWhite(g, o); tm = fasttm(L, udata.uv.metatable, TMS.TM_GC); if (tm != null) { LinyeeByteType oldah = L.allowhook; ly_mem oldt = (ly_mem)g.GCthreshold; L.allowhook = 0; /* stop debug hooks during GC tag method */ g.GCthreshold = 2 * g.totalbytes; /* avoid GC steps */ SetObj2S(L, L.top, tm); SetUValue(L, L.top + 1, udata); L.top += 2; LinyeeDCall(L, L.top - 2, 0); L.allowhook = oldah; /* restore hooks */ g.GCthreshold = (uint)oldt; /* restore threshold */ } }
private static GCObjectRef SweepList(LinyeeState L, GCObjectRef p, ly_mem count) { GCObject curr; GlobalState g = G(L); int deadmask = OtherWhite(g); while ((curr = p.get()) != null && count-- > 0) { if (curr.gch.tt == LINYEE_TTHREAD) /* sweep open upvalues of each thread */ { SweepWholeList(L, new OpenValRef(gco2th(curr))); } if (((curr.gch.marked ^ WHITEBITS) & deadmask) != 0) /* not dead? */ { LinyeeAssert(!IsDead(g, curr) || TestBit(curr.gch.marked, FIXEDBIT)); MakeWhite(g, curr); /* make it white (for next cycle) */ p = new NextRef(curr.gch); } else /* must erase `curr' */ { LinyeeAssert(IsDead(g, curr) || deadmask == BitMask(SFIXEDBIT)); p.set(curr.gch.next); if (curr == g.rootgc) /* is the first element of the list? */ { g.rootgc = curr.gch.next; /* adjust first */ } FreeObj(L, curr); } } return(p); }
/* ** Garbage-collection function */ public static int LinyeeGC(LinyeeState L, int what, int data) { int res = 0; GlobalState g; LinyeeLock(L); g = G(L); switch (what) { case LINYEE_GCSTOP: { g.GCthreshold = MAXLUMEM; break; } case LINYEE_GCRESTART: { g.GCthreshold = g.totalbytes; break; } case LINYEE_GCCOLLECT: { LinyeeCFullGC(L); break; } case LINYEE_GCCOUNT: { /* GC values are expressed in Kbytes: #bytes/2^10 */ res = CastInt(g.totalbytes >> 10); break; } case LINYEE_GCCOUNTB: { res = CastInt(g.totalbytes & 0x3ff); break; } case LINYEE_GCSTEP: { ly_mem a = ((ly_mem)data << 10); if (a <= g.totalbytes) { g.GCthreshold = (uint)(g.totalbytes - a); } else { g.GCthreshold = 0; } while (g.GCthreshold <= g.totalbytes) { LinyeeCStep(L); if (g.gcstate == GCSpause) /* end of cycle? */ { res = 1; /* signal it */ break; } } break; } case LINYEE_GCSETPAUSE: { res = g.gcpause; g.gcpause = data; break; } case LINYEE_GCSETSTEPMUL: { res = g.gcstepmul; g.gcstepmul = data; break; } default: res = -1; /* invalid option */ break; } LinyeeUnlock(L); return(res); }
private static l_mem SingleStep(LinyeeState L) { GlobalState g = G(L); /*ly_checkmemory(L);*/ switch (g.gcstate) { case GCSpause: { MarkRoot(L); /* start a new collection */ return(0); } case GCSpropagate: { if (g.gray != null) { return(PropagateMark(g)); } else /* no more `gray' objects */ { Atomic(L); /* finish mark phase */ return(0); } } case GCSsweepstring: { ly_mem old = (ly_mem)g.totalbytes; SweepWholeList(L, new ArrayRef(g.strt.hash, g.sweepstrgc++)); if (g.sweepstrgc >= g.strt.size) /* nothing more to sweep? */ { g.gcstate = GCSsweep; /* end sweep-string phase */ } LinyeeAssert(old >= g.totalbytes); g.estimate -= (uint)(old - g.totalbytes); return(GCSWEEPCOST); } case GCSsweep: { ly_mem old = (ly_mem)g.totalbytes; g.sweepgc = SweepList(L, g.sweepgc, GCSWEEPMAX); if (g.sweepgc.get() == null) /* nothing more to sweep? */ { CheckSizes(L); g.gcstate = GCSfinalize; /* end sweep phase */ } LinyeeAssert(old >= g.totalbytes); g.estimate -= (uint)(old - g.totalbytes); return(GCSWEEPMAX * GCSWEEPCOST); } case GCSfinalize: { if (g.tmudata != null) { GCTM(L); if (g.estimate > GCFINALIZECOST) { g.estimate -= GCFINALIZECOST; } return(GCFINALIZECOST); } else { g.gcstate = GCSpause; /* end collection */ g.gcdept = 0; return(0); } } default: LinyeeAssert(0); return(0); } }