static void persistfunction(PersistInfo *pi) { /* perms reftbl ... func */ Closure *cl = clvalue(getobject(pi->L, -1)); lua_checkstack(pi->L, 2); if(cl->c.isC) { /* It's a C function. For now, we aren't going to allow * persistence of C closures, even if the "C proto" is * already in the permanents table. */ lua_pushstring(pi->L, "Attempt to persist a C function"); lua_error(pi->L); } else { /* It's a Lua closure. */ { /* We don't really _NEED_ the number of upvals, * but it'll simplify things a bit */ pi->writer(pi->L, &cl->l.p->nups, sizeof(lu_byte), pi->ud); } /* Persist prototype */ { pushproto(pi->L, cl->l.p); /* perms reftbl ... func proto */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... func */ } /* Persist upvalue values (not the upvalue objects * themselves) */ { int i; for(i=0; i<cl->l.p->nups; i++) { /* perms reftbl ... func */ pushupval(pi->L, cl->l.upvals[i]); /* perms reftbl ... func upval */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... func */ } /* perms reftbl ... func */ } /* Persist function environment */ { lua_getfenv(pi->L, -1); /* perms reftbl ... func fenv */ if(lua_equal(pi->L, -1, LUA_GLOBALSINDEX)) { /* Function has the default fenv */ /* perms reftbl ... func _G */ lua_pop(pi->L, 1); /* perms reftbl ... func */ lua_pushnil(pi->L); /* perms reftbl ... func nil */ } /* perms reftbl ... func fenv/nil */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... func */ } } }
static void unboxupval(lua_State *L) { /* ... func */ LClosure *lcl; UpVal *uv; lcl = (LClosure*)clvalue(getobject(L, -1)); uv = lcl->upvals[0]; lua_pop(L, 1); /* ... */ pushupval(L, uv); /* ... upval */ }
static void unpersistupval(int ref, UnpersistInfo *upi) { /* perms reftbl ... */ UpVal *uv; unpersist(upi); /* perms reftbl ... obj */ uv = makeupval(upi->L, -1); lua_pop(upi->L, 1); /* perms reftbl ... */ pushupval(upi->L, uv); /* perms reftbl ... upval */ boxupval(upi->L); /* perms reftbl ... func */ }
/* Persist all stack members */ static void persistthread(PersistInfo *pi) { size_t posremaining; lua_State *L2; /* perms reftbl ... thr */ L2 = lua_tothread(pi->L, -1); lua_checkstack(pi->L, L2->top - L2->stack + 1); if(pi->L == L2) { lua_pushstring(pi->L, "Can't persist currently running thread"); lua_error(pi->L); return; /* not reached */ } /* Persist the stack */ posremaining = revappendstack(L2, pi->L); /* perms reftbl ... thr (rev'ed contents of L2) */ pi->writer(pi->L, &posremaining, sizeof(size_t), pi->ud); for(; posremaining > 0; posremaining--) { persist(pi); lua_pop(pi->L, 1); } /* perms reftbl ... thr */ /* Now, persist the CallInfo stack. */ { size_t i, numframes = (L2->ci - L2->base_ci) + 1; pi->writer(pi->L, &numframes, sizeof(size_t), pi->ud); for(i=0; i<numframes; i++) { CallInfo *ci = L2->base_ci + i; size_t stackbase = ci->base - L2->stack; size_t stackfunc = ci->func - L2->stack; size_t stacktop = ci->top - L2->stack; size_t savedpc = (ci != L2->base_ci) ? ci->savedpc - ci_func(ci)->l.p->code : 0; pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud); pi->writer(pi->L, &stackfunc, sizeof(size_t), pi->ud); pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud); pi->writer(pi->L, &ci->nresults, sizeof(int), pi->ud); pi->writer(pi->L, &savedpc, sizeof(size_t), pi->ud); } } /* Serialize the state's other parameters, with the exception of upval stuff */ { size_t stackbase = L2->base - L2->stack; size_t stacktop = L2->top - L2->stack; lua_assert(L2->nCcalls <= 1); pi->writer(pi->L, &L2->status, sizeof(lu_byte), pi->ud); pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud); pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud); pi->writer(pi->L, &L2->errfunc, sizeof(ptrdiff_t), pi->ud); } /* Finally, record upvalues which need to be reopened */ /* See the comment above persistupval() for why we do this */ { GCObject *gco; UpVal *uv; /* perms reftbl ... thr */ for(gco = L2->openupval; gco != NULL; gco = uv->next) { size_t stackpos; uv = gco2uv(gco); /* Make sure upvalue is really open */ lua_assert(uv->v != &uv->u.value); pushupval(pi->L, uv); /* perms reftbl ... thr uv */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... thr */ stackpos = uv->v - L2->stack; pi->writer(pi->L, &stackpos, sizeof(size_t), pi->ud); } /* perms reftbl ... thr */ lua_pushnil(pi->L); /* perms reftbl ... thr nil */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... thr */ } /* perms reftbl ... thr */ }
/* Persist all stack members */ static void persistthread(PersistInfo *pi) { int posremaining; lua_State *L2; /* perms reftbl ... thr */ L2 = lua_tothread(pi->L, -1); if(pi->L == L2) { lua_pushstring(pi->L, "Can't persist currently running thread"); lua_error(pi->L); return; /* not reached */ } posremaining = revappendstack(L2, pi->L); /* perms reftbl ... thr (rev'ed contents of L2) */ pi->writer(pi->L, &posremaining, sizeof(int), pi->ud); for(; posremaining > 0; posremaining--) { persist(pi); lua_pop(pi->L, 1); } /* perms reftbl ... thr */ /* Now, persist the CallInfo stack. */ { int i, numframes = (L2->ci - L2->base_ci) + 1; pi->writer(pi->L, &numframes, sizeof(int), pi->ud); for(i=0; i<numframes; i++) { CallInfo *ci = L2->base_ci + i; int stackbase = ci->base - L2->stack; int stacktop = ci->top - L2->stack; int pc = (ci != L2->base_ci) ? ci->u.l.savedpc - ci_func(ci)->l.p->code : 0; pi->writer(pi->L, &stackbase, sizeof(int), pi->ud); pi->writer(pi->L, &stacktop, sizeof(int), pi->ud); pi->writer(pi->L, &pc, sizeof(int), pi->ud); pi->writer(pi->L, &(ci->state), sizeof(int), pi->ud); } } /* Serialize the state's top and base */ { int stackbase = L2->base - L2->stack; int stacktop = L2->top - L2->stack; pi->writer(pi->L, &stackbase, sizeof(int), pi->ud); pi->writer(pi->L, &stacktop, sizeof(int), pi->ud); } /* Finally, record upvalues which need to be reopened */ /* See the comment above persistupval() for why we do this */ { UpVal *uv; /* perms reftbl ... thr */ for(uv = gcotouv(L2->openupval); uv != NULL; uv = gcotouv(uv->next)) { int stackpos; /* Make sure upvalue is really open */ lua_assert(uv->v != &uv->value); pushupval(pi->L, uv); /* perms reftbl ... thr uv */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... thr */ stackpos = uv->v - L2->stack; pi->writer(pi->L, &stackpos, sizeof(int), pi->ud); } /* perms reftbl ... thr */ lua_pushnil(pi->L); /* perms reftbl ... thr nil */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... thr */ } /* perms reftbl ... thr */ }