/* ** function to be used with macro "fasttm": optimized for absence of ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { const TValue *tm = luaR_isrotable(events) ? luaH_getstr_ro(events, ename) : luaH_getstr(events, ename); lua_assert(event <= TM_EQ); if (ttisnil(tm)) { /* no tag method? */ if (!luaR_isrotable(events)) events->flags |= cast_byte(1u<<event); /* cache this fact */ return NULL; } else return tm; }
static void reallymarkobject (global_State *g, GCObject *o) { lua_assert(iswhite(o) && !isdead(g, o)); white2gray(o); switch (o->gch.tt) { case LUA_TSTRING: { return; } case LUA_TUSERDATA: { Table *mt = gco2u(o)->metatable; gray2black(o); /* udata are never gray */ if (mt && !luaR_isrotable(mt)) markobject(g, mt); markobject(g, gco2u(o)->env); return; } case LUA_TUPVAL: { UpVal *uv = gco2uv(o); markvalue(g, uv->v); if (uv->v == &uv->u.value) /* closed? */ gray2black(o); /* open upvalues are never black */ return; } case LUA_TFUNCTION: { gco2cl(o)->c.gclist = g->gray; g->gray = o; break; } case LUA_TTABLE: { gco2h(o)->gclist = g->gray; g->gray = o; break; } case LUA_TTHREAD: { gco2th(o)->gclist = g->gray; g->gray = o; break; } case LUA_TPROTO: { gco2p(o)->gclist = g->gray; g->gray = o; break; } default: lua_assert(0); } }
static int traversetable (global_State *g, Table *h) { int i; int weakkey = 0; int weakvalue = 0; const TValue *mode; if (h->metatable && !luaR_isrotable(h->metatable)) markobject(g, h->metatable); mode = gfasttm(g, h->metatable, TM_MODE); if (mode && ttisstring(mode)) { /* is there a weak mode? */ weakkey = (c_strchr(svalue(mode), 'k') != NULL); weakvalue = (c_strchr(svalue(mode), 'v') != NULL); if (weakkey || weakvalue) { /* is really weak? */ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ h->marked |= cast_byte((weakkey << KEYWEAKBIT) | (weakvalue << VALUEWEAKBIT)); h->gclist = g->weak; /* must be cleared after GC, ... */ g->weak = obj2gco(h); /* ... so put in the appropriate list */ } } if (weakkey && weakvalue) return 1; if (!weakvalue) { i = h->sizearray; while (i--) markvalue(g, &h->array[i]); } i = sizenode(h); while (i--) { Node *n = gnode(h, i); lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); if (ttisnil(gval(n))) removeentry(n); /* remove empty entries */ else { lua_assert(!ttisnil(gkey(n))); if (!weakkey) markvalue(g, gkey(n)); if (!weakvalue) markvalue(g, gval(n)); } } return weakkey || weakvalue; }
const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { Table *mt; switch (ttype(o)) { case LUA_TTABLE: mt = hvalue(o)->metatable; break; case LUA_TROTABLE: mt = (Table *)luaR_getmeta(rvalue(o)); break; case LUA_TUSERDATA: mt = uvalue(o)->metatable; break; default: mt = G(L)->mt[ttype(o)]; } if (!mt) return luaO_nilobject; else if (luaR_isrotable(mt)) return luaH_getstr_ro(mt, G(L)->tmname[event]); else return luaH_getstr(mt, G(L)->tmname[event]); }
static void markmt (global_State *g) { int i; for (i=0; i<NUM_TAGS; i++) if (g->mt[i] && !luaR_isrotable(g->mt[i])) markobject(g, g->mt[i]); }