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 persistproto(PersistInfo *pi) { /* perms reftbl ... proto */ Proto *p = toproto(pi->L, -1); lua_checkstack(pi->L, 2); /* Persist constant refs */ { int i; pi->writer(pi->L, &p->sizek, sizeof(int), pi->ud); for(i=0; i<p->sizek; i++) { LIF(A,pushobject)(pi->L, &p->k[i]); /* perms reftbl ... proto const */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... proto */ } } /* perms reftbl ... proto */ /* serialize inner Proto refs */ { int i; pi->writer(pi->L, &p->sizep, sizeof(int), pi->ud); for(i=0; i<p->sizep; i++) { pushproto(pi->L, p->p[i]); /* perms reftbl ... proto subproto */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... proto */ } } /* perms reftbl ... proto */ /* Serialize code */ { pi->writer(pi->L, &p->sizecode, sizeof(int), pi->ud); pi->writer(pi->L, p->code, sizeof(Instruction) * p->sizecode, pi->ud); } /* Serialize misc values */ { pi->writer(pi->L, &p->nups, sizeof(lu_byte), pi->ud); pi->writer(pi->L, &p->numparams, sizeof(lu_byte), pi->ud); pi->writer(pi->L, &p->is_vararg, sizeof(lu_byte), pi->ud); pi->writer(pi->L, &p->maxstacksize, sizeof(lu_byte), pi->ud); } /* We do not currently persist upvalue names, local variable names, * variable lifetimes, line info, or source code. */ }
static void unpersistproto(int ref, UnpersistInfo *upi) { /* perms reftbl ... */ Proto *p; int i; int sizep, sizek; /* We have to be careful. The GC expects a lot out of protos. In * particular, we need to give the function a valid string for its * source, and valid code, even before we actually read in the real * code. */ TString *source = luaS_newlstr(upi->L, "", 0); p = luaF_newproto(upi->L); p->source = source; p->sizecode=1; p->code = luaM_newvector(upi->L, 1, Instruction); p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); p->maxstacksize = 2; p->sizek = 0; p->sizep = 0; pushproto(upi->L, p); /* perms reftbl ... proto */ /* We don't need to register early, since protos can never ever be * involved in cyclic references */ /* Read in constant references */ { verify(luaZ_read(&upi->zio, &sizek, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->k, 0, sizek, TObject); for(i=0; i<sizek; i++) { /* perms reftbl ... proto */ unpersist(upi); /* perms reftbl ... proto k */ setobj2s(&p->k[i], getobject(upi->L, -1)); p->sizek++; lua_pop(upi->L, 1); /* perms reftbl ... proto */ } /* perms reftbl ... proto */ } /* Read in sub-proto references */ { verify(luaZ_read(&upi->zio, &sizep, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->p, 0, sizep, Proto*); for(i=0; i<sizep; i++) { /* perms reftbl ... proto */ unpersist(upi); /* perms reftbl ... proto subproto */ p->p[i] = toproto(upi->L, -1); p->sizep++; lua_pop(upi->L, 1); /* perms reftbl ... proto */ } /* perms reftbl ... proto */ } /* Read in code */ { verify(luaZ_read(&upi->zio, &p->sizecode, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->code, 1, p->sizecode, Instruction); verify(luaZ_read(&upi->zio, p->code, sizeof(Instruction) * p->sizecode) == 0); } /* Read in misc values */ { verify(luaZ_read(&upi->zio, &p->nups, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->numparams, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->is_vararg, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->maxstacksize, sizeof(lu_byte)) == 0); } }