static l_mem singlestep (lua_State *L) { global_State *g = G(L); switch (g->gcstate) { case GCSpause: { if (!isgenerational(g)) markroot(g); /* start a new collection */ /* in any case, root must be marked */ lua_assert(!iswhite(obj2gco(g->mainthread)) && !iswhite(gcvalue(&g->l_registry))); g->gcstate = GCSpropagate; return GCROOTCOST; } case GCSpropagate: { if (g->gray) return propagatemark(g); else { /* no more `gray' objects */ g->gcstate = GCSatomic; /* finish mark phase */ atomic(L); return GCATOMICCOST; } } case GCSsweepstring: { if (g->sweepstrgc < g->strt.size) { sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); return GCSWEEPCOST; } else { /* no more strings to sweep */ g->sweepgc = &g->finobj; /* prepare to sweep finalizable objects */ g->gcstate = GCSsweepudata; return 0; } } case GCSsweepudata: { if (*g->sweepgc) { g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); return GCSWEEPMAX*GCSWEEPCOST; } else { g->sweepgc = &g->allgc; /* go to next phase */ g->gcstate = GCSsweep; return GCSWEEPCOST; } } case GCSsweep: { if (*g->sweepgc) { g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); return GCSWEEPMAX*GCSWEEPCOST; } else { /* sweep main thread */ GCObject *mt = obj2gco(g->mainthread); sweeplist(L, &mt, 1); checkSizes(L); g->gcstate = GCSpause; /* finish collection */ return GCSWEEPCOST; } } default: lua_assert(0); return 0; } }
static size_t mark (lua_State *L) { size_t deadmem; GCState st; GCObject *wkv; st.L = L; st.g = G(L); st.tmark = NULL; st.wkv = st.wk = st.wv = NULL; markroot(&st, L); propagatemarks(&st); /* mark all reachable objects */ cleartablevalues(L, st.wkv); cleartablevalues(L, st.wv); wkv = st.wkv; /* keys must be cleared after preserving udata */ st.wkv = NULL; st.wv = NULL; deadmem = luaC_separateudata(L); /* separate userdata to be preserved */ marktmu(&st); /* mark `preserved' userdata */ propagatemarks(&st); /* remark, to propagate `preserveness' */ cleartablekeys(L, wkv); /* `propagatemarks' may resuscitate some weak tables; clear them too */ cleartablekeys(L, st.wk); cleartablevalues(L, st.wv); cleartablekeys(L, st.wkv); cleartablevalues(L, st.wkv); return deadmem; }
void luaC_fullgc (lua_State *L) { global_State *g = G(L); if(is_block_gc(L)) return; set_block_gc(L); if (g->gcstate <= GCSpropagate) { /* reset sweep marks to sweep all elements (returning them to white) */ g->sweepstrgc = 0; g->sweepgc = &g->rootgc; /* reset other collector lists */ g->gray = NULL; g->grayagain = NULL; g->weak = NULL; g->gcstate = GCSsweepstring; } lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); /* finish any pending sweep phase */ while (g->gcstate != GCSfinalize) { lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); singlestep(L); } markroot(L); while (g->gcstate != GCSpause) { singlestep(L); } setthreshold(g); unset_block_gc(L); }
static l_mem singlestep(lua_State *L) { global_State *g = G(L); /*lua_checkmemory(L);*/ switch (g->gcstate) { case GCSpause: { markroot(L); /* start a new collection */ return 0; } case GCSpropagate: { if (g->gray) return propagatemark(g); else { /* no more `gray' objects */ atomic(L); /* finish mark phase */ return 0; } } case GCSsweepstring: { lu_mem old = g->totalbytes; sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ g->gcstate = GCSsweep; /* end sweep-string phase */ lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes; return GCSWEEPCOST; } case GCSsweep: { lu_mem old = g->totalbytes; g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); if (*g->sweepgc == NULL) { /* nothing more to sweep? */ checkSizes(L); g->gcstate = GCSfinalize; /* end sweep phase */ } lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes; return GCSWEEPMAX * GCSWEEPCOST; } case GCSfinalize: { if (g->tmudata) { GCTM(L); if (g->estimate > GCFINALIZECOST) g->estimate -= GCFINALIZECOST; return GCFINALIZECOST; } else { g->gcstate = GCSpause; /* end collection */ g->gcdept = 0; return 0; } } default: lua_assert(0); return 0; } }
// lua的gc状态机,执行顺序和下面的状态的从大到小开始一致 static l_mem singlestep (lua_State *L) { global_State *g = G(L); /*lua_checkmemory(L);*/ switch (g->gcstate) { case GCSpause: {// 初始状态 markroot(L); /* start a new collection */// 主要就是标记主线程对象(也就是从白色染成灰色) return 0; } case GCSpropagate: {// 这个状态也是一个标记过程,并且会被进入多次,也就是分布迭代 if (g->gray)// 如果gray对象一直存在的话,反复调用propagatemark函数,等所有的gray对象都被标记了,就会进入atomic函数处理 return propagatemark(g); else { /* no more `gray' objects */ atomic(L); /* finish mark phase */// 原子操作 return 0; } } case GCSsweepstring: {// 清理字符串的阶段 lu_mem old = g->totalbytes; sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ g->gcstate = GCSsweep; /* end sweep-string phase */ lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes; return GCSWEEPCOST; } case GCSsweep: { lu_mem old = g->totalbytes; g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); if (*g->sweepgc == NULL) { /* nothing more to sweep? */ checkSizes(L); g->gcstate = GCSfinalize; /* end sweep phase */ } lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes; return GCSWEEPMAX*GCSWEEPCOST; } case GCSfinalize: { if (g->tmudata) { GCTM(L); if (g->estimate > GCFINALIZECOST) g->estimate -= GCFINALIZECOST; return GCFINALIZECOST; } else { g->gcstate = GCSpause; /* end collection */ g->gcdept = 0; return 0; } } default: lua_assert(0); return 0; } }
static lu_mem singlestep (lua_State *L) { global_State *g = G(L); switch (g->gcstate) { case GCSpause: { g->GCmemtrav = 0; /* start to count memory traversed */ if (!isgenerational(g)) markroot(g); /* start a new collection */ /* in any case, root must be marked at this point */ lua_assert(!iswhite(obj2gco(g->mainthread)) && !iswhite(gcvalue(&g->l_registry))); g->gcstate = GCSpropagate; return g->GCmemtrav; } case GCSpropagate: { if (g->gray) { lu_mem oldtrav = g->GCmemtrav; propagatemark(g); return g->GCmemtrav - oldtrav; /* memory traversed in this step */ } else { /* no more `gray' objects */ lu_mem work; int sw; g->gcstate = GCSatomic; /* finish mark phase */ g->GCestimate = g->GCmemtrav; /* save what was counted */; work = atomic(L); /* add what was traversed by 'atomic' */ g->GCestimate += work; /* estimate of total memory traversed */ sw = entersweep(L); return work + sw * GCSWEEPCOST; } } case GCSsweepstring: { int i; for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); g->sweepstrgc += i; if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ g->gcstate = GCSsweepudata; return i * GCSWEEPCOST; } case GCSsweepudata: { if (g->sweepfin) { g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); return GCSWEEPMAX*GCSWEEPCOST; } else { g->gcstate = GCSsweep; return 0; } } case GCSsweep: { if (g->sweepgc) { g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); return GCSWEEPMAX*GCSWEEPCOST; } else { /* sweep main thread */ GCObject *mt = obj2gco(g->mainthread); sweeplist(L, &mt, 1); checkSizes(L); g->gcstate = GCSpause; /* finish collection */ return GCSWEEPCOST; } } default: lua_assert(0); return 0; } }